Skip to main content

Quick Integration (Any Language)

Integrate SyAuth using standard HTTP requests from any programming language.


Before You Begin

info

You need these credentials before starting. Get them from the SyAuth Dashboard.

What You NeedWhere to Find ItExample
Client IDDashboard → OAuth Clients → Your Appa1b2c3d4-5678-90ab-cdef-...
Redirect URIYou configure this in Dashboard → OAuth Clients → Redirect URIshttp://localhost:3000/callback

New to SyAuth? Follow these steps first:

  1. Create a Nexorix account (SyAuth uses Nexorix for authentication)
  2. Create your first Application to get your Client ID

How OAuth Authentication Works

Before diving into code, here's what happens when a user logs in:


Step 1: Generate PKCE Codes

What is PKCE? It's a security feature that prevents attackers from intercepting the authorization code. You generate two related values:

  • code_verifier — A random secret string (keep this safe!)
  • code_challenge — A hashed version of the verifier (sent to SyAuth)
import secrets
import hashlib
import base64

# Generate a random 32-byte string, base64url encoded
code_verifier = base64.urlsafe_b64encode(secrets.token_bytes(32)).decode('utf-8').rstrip('=')

# Create SHA256 hash of verifier, then base64url encode
code_challenge = base64.urlsafe_b64encode(
hashlib.sha256(code_verifier.encode('utf-8')).digest()
).decode('utf-8').rstrip('=')

# IMPORTANT: Store code_verifier in session - you'll need it in Step 3!
print(f"code_verifier: {code_verifier}")
print(f"code_challenge: {code_challenge}")
CAUTION

Store the code_verifier securely! You'll need it in Step 3 to exchange the authorization code for tokens. If you lose it, you'll have to start over.


Step 2: Redirect User to Login

Build the authorization URL and redirect the user's browser to SyAuth:

GET https://api.syauth.com/e/v1/oauth/authorize
?response_type=code
&client_id=YOUR_CLIENT_ID
&redirect_uri=YOUR_REDIRECT_URI
&scope=openid profile email
&state=RANDOM_STATE
&code_challenge=YOUR_CODE_CHALLENGE
&code_challenge_method=S256

Parameter Reference

ParameterRequiredValueDescription
response_typecodeAlways use code for the authorization code flow
client_idYour Client IDFind this in Dashboard → OAuth Clients → Your App
redirect_uriYour callback URLMust exactly match what you configured in Dashboard
scopeopenid profile emailPermissions to request (standard OIDC scopes)
stateRandom stringGenerate a unique value to prevent CSRF attacks. Verify it matches in Step 3
code_challengeFrom Step 1The code_challenge you generated
code_challenge_methodS256Always use S256 (SHA-256 hashing)

Example: Building the URL

from urllib.parse import urlencode
import secrets

# Your app's configuration
CLIENT_ID = "your-client-id-from-dashboard" # <-- Get from Dashboard
REDIRECT_URI = "http://localhost:3000/callback" # <-- Must match Dashboard config

# Generate state for CSRF protection
state = secrets.token_urlsafe(32)

# Build authorization URL
params = {
'response_type': 'code',
'client_id': CLIENT_ID,
'redirect_uri': REDIRECT_URI,
'scope': 'openid profile email',
'state': state,
'code_challenge': code_challenge, # From Step 1
'code_challenge_method': 'S256'
}

auth_url = f"https://api.syauth.com/e/v1/oauth/authorize?{urlencode(params)}"

# Store state in session to verify later
session['oauth_state'] = state

# Redirect user to this URL
print(f"Redirect to: {auth_url}")

After the user logs in successfully, SyAuth redirects them back to your redirect_uri with an authorization code.


Step 3: Exchange Code for Tokens

When the user is redirected back to your app, the URL will look like:

https://your-app.com/callback?code=AUTHORIZATION_CODE&state=SAME_STATE_YOU_SENT

Before exchanging the code:

  1. ✅ Verify the state matches what you stored (prevents CSRF attacks)
  2. ✅ Extract the code parameter

Now exchange the code for access tokens:

curl -X POST https://api.syauth.com/e/v1/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=THE_CODE_FROM_CALLBACK" \
-d "client_id=YOUR_CLIENT_ID" \
-d "redirect_uri=YOUR_REDIRECT_URI" \
-d "code_verifier=YOUR_CODE_VERIFIER_FROM_STEP_1"

Token Response

{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 3600,
"refresh_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
}
FieldDescription
access_tokenUse this to authenticate API requests. Valid for 1 hour.
refresh_tokenUse this to get a new access token when the current one expires.
expires_inSeconds until the access token expires (3600 = 1 hour).
tip

Store tokens securely! Use HTTP-only cookies or secure server-side storage. Never expose tokens in client-side JavaScript where they can be accessed by malicious scripts.


Step 4: Call APIs with the Access Token

Use the access_token to make authenticated requests:

# Replace with your actual access token from Step 3
curl https://api.syauth.com/e/v1/user/profile \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

Example Response

{
"id": "550e8400-e29b-41d4-a716-446655440000",
"email": "[email protected]",
"first_name": "John",
"last_name": "Doe",
"email_verified": true
}

Step 5: Refresh Expired Tokens

Access tokens expire after 1 hour. Use the refresh_token to get a new access token without requiring the user to log in again:

response = requests.post('https://api.syauth.com/e/v1/oauth/token', data={
'grant_type': 'refresh_token',
'refresh_token': refresh_token,
'client_id': CLIENT_ID
})

new_tokens = response.json()
new_access_token = new_tokens['access_token']
# Also update the refresh_token if a new one is provided

Troubleshooting

"Invalid redirect_uri" Error

Cause: The redirect_uri in your request doesn't exactly match what's configured in the Dashboard.

Fix:

  1. Go to Dashboard → OAuth Clients → Your App → Edit Settings → Redirect URIs
  2. Ensure the URI matches exactly (including http vs https, trailing slashes, etc.)

"Invalid code_verifier" Error

Cause: The code_verifier doesn't match the code_challenge sent during authorization.

Fix:

  • Make sure you're using the same code_verifier you generated in Step 1
  • Check that you stored it in the session and retrieved it correctly

"Invalid or expired code" Error

Cause: Authorization codes expire after 10 minutes and can only be used once.

Fix:

  • Complete the token exchange immediately after receiving the callback
  • Don't refresh the callback page (this tries to use the code again)

Complete Example

Full Python Flask Example
from flask import Flask, redirect, request, session
import requests
import secrets
import hashlib
import base64
from urllib.parse import urlencode

app = Flask(__name__)
# IMPORTANT: In production, use a secure, random environment variable
app.secret_key = 'your-secret-key'

# Configuration - get these from your SyAuth Dashboard
CLIENT_ID = 'your-client-id'
REDIRECT_URI = 'http://localhost:5000/callback'

@app.route('/login')
def login():
# Step 1: Generate PKCE
code_verifier = base64.urlsafe_b64encode(secrets.token_bytes(32)).decode().rstrip('=')
code_challenge = base64.urlsafe_b64encode(
hashlib.sha256(code_verifier.encode()).digest()
).decode().rstrip('=')

# Store verifier for later
session['pkce_verifier'] = code_verifier

# Generate state
state = secrets.token_urlsafe(32)
session['oauth_state'] = state

# Step 2: Redirect to SyAuth
params = {
'response_type': 'code',
'client_id': CLIENT_ID,
'redirect_uri': REDIRECT_URI,
'scope': 'openid profile email',
'state': state,
'code_challenge': code_challenge,
'code_challenge_method': 'S256'
}

return redirect(f"https://api.syauth.com/e/v1/oauth/authorize?{urlencode(params)}")

@app.route('/callback')
def callback():
# Verify state
if request.args.get('state') != session.get('oauth_state'):
return "Invalid state!", 400

# Step 3: Exchange code for tokens
response = requests.post('https://api.syauth.com/e/v1/oauth/token', data={
'grant_type': 'authorization_code',
'code': request.args.get('code'),
'client_id': CLIENT_ID,
'redirect_uri': REDIRECT_URI,
'code_verifier': session.get('pkce_verifier')
})

tokens = response.json()
session['access_token'] = tokens['access_token']

return redirect('/profile')

@app.route('/profile')
def profile():
# Step 4: Use access token
response = requests.get(
'https://api.syauth.com/e/v1/user/profile',
headers={'Authorization': f"Bearer {session.get('access_token')}"}
)

user = response.json()
return f"Hello, {user['first_name']}!"

if __name__ == '__main__':
app.run(port=5000)

Next Steps