Authorize a customer with PKCE
Implement the ShareAI authorization-code flow with S256 PKCE, verify state and exchange the code on your application backend.
On this page
This flow connects one customer account to your application. The customer signs in, chooses a personal or organization account and approves the requested permissions. Your backend then exchanges the short-lived code for tokens.
Before you start#
Complete application registration. You need an exact registered callback, server-held client credentials and a server-side session for the browser completing authorization.
1. Create the authorization request#
https://auth.shareai.now/oauth/authorizeAsk the customer to authorize the application.
- Base URL
https://auth.shareai.now- Authentication
- Browser redirect; registered application
Generate a fresh verifier, state and nonce for each attempt. Store them in the initiating user’s server-side session. Send the SHA-256 challenge, never the verifier, in the browser redirect. Request only the scopes your application needs.
Python
import base64
import hashlib
import secrets
import urllib.parse
verifier = secrets.token_urlsafe(48)
challenge = base64.urlsafe_b64encode(hashlib.sha256(verifier.encode()).digest()).rstrip(b"=").decode()
state = secrets.token_urlsafe(32)
nonce = secrets.token_urlsafe(32)
# Store verifier, state and nonce in the user's server-side session.
params = {
"response_type": "code",
"client_id": "YOUR_CLIENT_ID",
"redirect_uri": "https://app.example.com/auth/shareai/callback",
"scope": "openid profile surcharge",
"state": state,
"nonce": nonce,
"code_challenge": challenge,
"code_challenge_method": "S256",
}
print("https://auth.shareai.now/oauth/authorize?" + urllib.parse.urlencode(params))
TypeScript
import { randomBytes, createHash } from "node:crypto";
const verifier = randomBytes(48).toString("base64url");
const state = randomBytes(32).toString("base64url");
const nonce = randomBytes(32).toString("base64url");
const challenge = createHash("sha256").update(verifier).digest("base64url");
// Save verifier, state and nonce in the initiating server-side session.
const params = new URLSearchParams({ response_type: "code", client_id: "YOUR_CLIENT_ID",
redirect_uri: "https://app.example.com/auth/shareai/callback",
scope: "openid profile surcharge", state, nonce,
code_challenge: challenge, code_challenge_method: "S256" });
const authorizationUrl = `https://auth.shareai.now/oauth/authorize?${params}`;
// Redirect the browser to authorizationUrl.
2. Validate the callback#
If authorization is declined, handle the OAuth error as a normal cancellation. Otherwise compare the returned state with the saved value before using the code. Reject a missing or mismatched state. Consume the saved state once; do not accept callback URLs submitted by another browser session.
3. Exchange the code#
https://auth.shareai.now/oauth/tokenExchange a one-use code and the matching PKCE verifier.
- Base URL
https://auth.shareai.now- Authentication
- Confidential client authentication
cURL
curl --fail-with-body "https://auth.shareai.now/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "grant_type=authorization_code" \
--data-urlencode "client_id=$SHAREAI_CLIENT_ID" \
--data-urlencode "client_secret=$SHAREAI_CLIENT_SECRET" \
--data-urlencode "code=$AUTHORIZATION_CODE" \
--data-urlencode "redirect_uri=https://app.example.com/auth/shareai/callback" \
--data-urlencode "code_verifier=$PKCE_VERIFIER"
Use the client authentication method configured for the client. The example uses form-based client authentication. Do not send the same code twice; start authorization again after a consumed or expired code.
4. Store the result and establish your app session#
Store access and refresh tokens in your backend. Use the returned expires_in rather than assuming a permanent token. If you use an ID token, validate its signature with the issuer’s JWKS, expected issuer, client audience, expiry and your original nonce before trusting claims.
Continue the lifecycle#
Refresh and rotation · Scopes and account identity · OAuth chat requests
Last updated September 15, 2026