The Authorization Code Flow is the recommended OAuth2 flow for server-side applications where the client secret can be securely stored.
┌──────────┐
│ User │
└─────┬────┘
│ 1. Initiate login
▼
┌──────────────┐
│ Your App │
└──────┬───────┘
│ 2. Redirect to authorization URL
▼
┌──────────┐
│ Askara │
└────┬─────┘
│ 3. Show login/consent page
▼
┌──────────┐
│ User │
└────┬─────┘
│ 4. Authorize application
▼
┌──────────┐
│ Askara │
└────┬─────┘
│ 5. Redirect with authorization code
▼
┌──────────────┐
│ Your App │
└──────┬───────┘
│ 6. Exchange code for token
▼
┌──────────┐
│ Askara │
└────┬─────┘
│ 7. Return access & refresh tokens
▼
┌──────────────┐
│ Your App │
└──────┬───────┘
│ 8. Authentication complete
▼
┌──────────┐
│ User │
└──────────┘Generate a random state parameter for CSRF protection and store it securely (session, cookie, or database).
Build the authorization URL:
https://app.askara.ai/authorize?response_type=code&client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&scope=profile%20organization&state=STATEParameters:
response_type: Must becodeclient_id: Your application's client IDredirect_uri: Your callback URL (must match registration)scope: Space-separated list of permissions (profile organization)state: Random string for CSRF protection (required)code_challengeandcode_challenge_method: PKCE parameters (S256). Required for public clients, that is clients without a client secret, and for any client configured to require PKCE. See PKCE.
Redirect the user to this URL. They will authenticate and authorize your application.
After authorization, Askara redirects to your redirect_uri with query parameters:
https://your-app.com/callback?code=AUTHORIZATION_CODE&state=STATEVerify the state parameter matches your stored value to prevent CSRF attacks.
Make a server-side POST request to exchange the authorization code for tokens. The body must be form-encoded, as defined by the OAuth2 specification (RFC 6749):
POST https://api.askara.ai/oauth2/token
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code&code=AUTHORIZATION_CODE&redirect_uri=REDIRECT_URI&client_id=CLIENT_ID&client_secret=CLIENT_SECRETSend client_secret if your client is confidential. A public client has no secret: it sends the PKCE code_verifier instead (see PKCE).
Response:
{
"token_type": "Bearer",
"expires_in": 3600,
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"refresh_token": "def502003f8a8c7..."
}Important: Store both tokens securely in your database.
Include the access token in API requests:
GET https://api.askara.ai/me
Authorization: Bearer ACCESS_TOKEN
Content-Type: application/json- Generate a cryptographically secure random string (minimum 16 characters)
- Store securely and validate on callback
- Use once and discard after validation
- Generate a random
code_verifierfor each authorization request and keep it on your side - Send
code_challenge(the base64url-encoded SHA-256 hash of the verifier) withcode_challenge_method=S256in the authorization URL - Send the original
code_verifierwhen you exchange the code in Step 3 - Required for public clients, optional for confidential clients unless Askara configured your client to require it
- Never expose in client-side code
- Store in environment variables or secure configuration
- Use HTTPS for all token exchanges
- Single-use only
- Short-lived (valid for 10 minutes)
- Must be exchanged on server-side
Only a successful authorization redirects to your redirect_uri (with code and state). If the authorization request is invalid (for example invalid_request for missing or invalid parameters, or unauthorized_client for a client that is not allowed to use this flow), Askara shows the error to the user on its own authorization page and does not call your callback.
Do not rely on an error redirect: your application must also handle a user who denies or abandons the authorization without ever reaching your redirect_uri, for example with a timeout on the login attempt.
{
"error": "invalid_grant",
"error_description": "The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client.",
"hint": "Authorization code has expired"
}Rely on the error value only: error_description and hint are meant for debugging and their wording may change.
Common errors:
invalid_grant(HTTP400): Code expired or already usedinvalid_client(HTTP401): Invalid client credentialsinvalid_request(HTTP400): Missing required parameters
// Step 1: Generate authorization URL
$state = bin2hex(random_bytes(16));
$_SESSION['oauth_state'] = $state;
$authUrl = 'https://app.askara.ai/authorize?' . http_build_query([
'response_type' => 'code',
'client_id' => getenv('ASKARA_CLIENT_ID'),
'redirect_uri' => 'https://your-app.com/callback',
'scope' => 'profile organization',
'state' => $state
]);
header('Location: ' . $authUrl);
// Step 2: Handle callback
if ($_GET['state'] !== $_SESSION['oauth_state']) {
die('Invalid state parameter');
}
$code = $_GET['code'];
// Step 3: Exchange code for token
$response = $httpClient->post('https://api.askara.ai/oauth2/token', [
'form_params' => [
'grant_type' => 'authorization_code',
'code' => $code,
'redirect_uri' => 'https://your-app.com/callback',
'client_id' => getenv('ASKARA_CLIENT_ID'),
'client_secret' => getenv('ASKARA_CLIENT_SECRET')
]
]);
$tokens = json_decode($response->getBody(), true);
// Store $tokens['access_token'] and $tokens['refresh_token']- Refresh Token Flow - Renew expired access tokens
- API Reference - Available API endpoints
- OAuth2 Overview - Other authentication flows