On this page
- 1. Register your OAuth application
- Option A: Through the dashboard (recommended)
- Option B: Dynamic client registration
- 2. Generate a PKCE code challenge
- 3. Redirect the user to Glossia
- 4. Exchange the code for tokens
- 5. Call the API on behalf of the user
- 6. Refresh the token
- 7. Revoke a token
- Choosing scopes
- Discovery endpoints
- Error handling
- Authorization errors
- Token errors
- Rate limits
- Security checklist
Login with Glossia
MarkdownLet users sign in to your app with their Glossia account using OAuth 2.1.
This guide walks you through adding "Login with Glossia" to your application. By the end, your users will be able to sign in with their Glossia account and your app will have an access token to call the Glossia API on their behalf.
Glossia uses OAuth 2.1 with PKCE (Proof Key for Code Exchange). PKCE is required for all clients, including server-side applications.
1. Register your OAuth application
You have two options for registering your application:
Option A: Through the dashboard (recommended)
- Sign in to Glossia and go to your account dashboard.
- Open the API section from the sidebar and click OAuth apps.
- Click New application.
- Fill in the application name and callback URL (also called redirect URI).
- Click Create application.
After creation, note the Client ID and Client secret. The secret is shown once, so store it securely.
Option B: Dynamic client registration
Send a POST request to /oauth/register:
curl -X POST https://glossia.ai/oauth/register \
-H "Content-Type: application/json" \
-d '{
"client_name": "My App",
"redirect_uris": ["https://myapp.com/auth/callback"],
"grant_types": ["authorization_code"]
}'
The response includes client_id and client_secret.
2. Generate a PKCE code challenge
Before redirecting the user, generate a PKCE code verifier and challenge:
function generateCodeVerifier() {
const array = new Uint8Array(32);
crypto.getRandomValues(array);
return btoa(String.fromCharCode(...array))
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=+$/, "");
}
async function generateCodeChallenge(verifier) {
const encoder = new TextEncoder();
const data = encoder.encode(verifier);
const digest = await crypto.subtle.digest("SHA-256", data);
return btoa(String.fromCharCode(...new Uint8Array(digest)))
.replace(/\+/g, "-")
.replace(/\//g, "_")
.replace(/=+$/, "");
}
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
// Store codeVerifier in your session -- you will need it in step 4
3. Redirect the user to Glossia
Build the authorization URL and redirect the user's browser:
https://glossia.ai/oauth/authorize?
response_type=code
&client_id=YOUR_CLIENT_ID
&redirect_uri=https://myapp.com/auth/callback
&code_challenge=YOUR_CODE_CHALLENGE
&code_challenge_method=S256
&scope=user:read+project:read
&state=RANDOM_STATE_VALUE
Parameters:
| Parameter | Required | Description |
|---|---|---|
response_type |
Yes | Always code |
client_id |
Yes | Your application's client ID |
redirect_uri |
Yes | Must match a registered callback URL |
code_challenge |
Yes | The PKCE code challenge (S256) |
code_challenge_method |
Yes | Always S256 |
scope |
No | Space-separated list of scopes. Defaults to minimum access if omitted |
state |
Recommended | A random string to prevent CSRF attacks. Verify it matches when the user returns |
The user will see a consent screen showing your application name and the requested scopes. After they approve, Glossia redirects back to your callback URL with an authorization code.
4. Exchange the code for tokens
When the user is redirected back to your callback URL, the URL will contain a code parameter:
https://myapp.com/auth/callback?code=AUTHORIZATION_CODE&state=RANDOM_STATE_VALUE
First, verify that state matches what you sent in step 3. Then exchange the code for tokens:
curl -X POST https://glossia.ai/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=authorization_code" \
-d "code=AUTHORIZATION_CODE" \
-d "redirect_uri=https://myapp.com/auth/callback" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET" \
-d "code_verifier=YOUR_CODE_VERIFIER"
The response:
{
"access_token": "eyJhbGciOiJSUzI1...",
"token_type": "bearer",
"expires_in": 3600,
"refresh_token": "dGhpcyBpcyBhIHJl..."
}
Store both tokens securely. The access token is used for API requests. The refresh token is used to get a new access token when the current one expires.
5. Call the API on behalf of the user
Use the access token to make authenticated API requests:
curl -H "Authorization: Bearer eyJhbGciOiJSUzI1..." \
https://glossia.ai/api/projects
The token's scopes limit what endpoints you can access. Resource-level authorization still applies -- for example, a token with project:read can only read projects the user has access to.
6. Refresh the token
When the access token expires, use the refresh token to get a new one without sending the user through the consent flow again:
curl -X POST https://glossia.ai/oauth/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=refresh_token" \
-d "refresh_token=dGhpcyBpcyBhIHJl..." \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET"
7. Revoke a token
When a user disconnects your app or you no longer need access, revoke the token:
curl -X POST https://glossia.ai/oauth/revoke \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "token=eyJhbGciOiJSUzI1..." \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET"
Choosing scopes
Request only the scopes your application needs. Here are some common combinations:
| Use case | Scopes |
|---|---|
| Read user profile | user:read |
| Read projects and content | user:read project:read voice:read |
| Manage projects | user:read project:read project:write |
| Full organization access | user:read organization:read organization:write members:read members:write project:read project:write |
See the full scopes reference for all available scopes.
Discovery endpoints
Your application can discover Glossia's OAuth endpoints automatically by fetching the server metadata:
curl https://glossia.ai/.well-known/oauth-authorization-server
This returns a JSON document with the authorization_endpoint, token_endpoint, revocation_endpoint, and other details. Using discovery makes your integration resilient to endpoint changes.
Error handling
Authorization errors
If the user denies consent or something goes wrong during authorization, Glossia redirects to your callback URL with an error parameter:
https://myapp.com/auth/callback?error=access_denied&state=RANDOM_STATE_VALUE
Common error codes:
| Error | Meaning |
|---|---|
access_denied |
The user denied the authorization request |
invalid_request |
The request is missing a required parameter |
invalid_scope |
One or more requested scopes are not valid |
Token errors
The token endpoint returns HTTP 400 with a JSON error body:
{
"error": "invalid_grant",
"error_description": "The authorization code has expired or was already used."
}
Rate limits
OAuth endpoints are rate limited per IP. If you hit the limit, you will receive HTTP 429. See the rate limiting reference for details.
Security checklist
Before going to production, verify that your implementation follows these practices:
- Always use HTTPS for callback URLs in production
- Validate the
stateparameter on the callback to prevent CSRF - Store tokens encrypted at rest
- Never expose tokens in client-side JavaScript or browser URLs
- Use the minimum set of scopes needed
- Handle token expiration gracefully with refresh tokens
- Revoke tokens when users disconnect or delete their account
Glossia