The authentication flow differs based on whether you’re using a private or public application.
Private Application Flow (Authorization Code)
-
Redirect Users to Authorization URL
Construct the authorization URL with your client_id
and callback_url
:
const authUrl = new URL("https://clerk.coloop.ai/oauth/authorize");
authUrl.searchParams.append("client_id", "your_client_id");
authUrl.searchParams.append("redirect_uri", "your_callback_url");
authUrl.searchParams.append("response_type", "code");
authUrl.searchParams.append("scope", "email profile");
// Redirect user to authUrl
-
Handle the Callback
After authorization, CoLoop redirects to your callback URL with an authorization code:
// Example callback URL:
// https://your-domain.com/oauth2/callback?code=abc123...
-
Exchange Code for Tokens
Make a POST request to the token endpoint:
const response = await fetch("https://clerk.coloop.ai/oauth/token", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: new URLSearchParams({
grant_type: "authorization_code",
client_id: "your_client_id",
client_secret: "your_client_secret",
code: "authorization_code_from_callback",
redirect_uri: "your_callback_url"
})
});
const tokens = await response.json();
// {
// "access_token": "...",
// "refresh_token": "...",
// "scope": "email profile",
// "token_type": "bearer",
// "expires_in": 7200
// }
Public Application Flow (PKCE)
-
Generate PKCE Challenge
// Generate a random code verifier
function generateCodeVerifier() {
const array = new Uint8Array(32);
crypto.getRandomValues(array);
return base64UrlEncode(array);
}
// Create code challenge
async function generateCodeChallenge(verifier) {
const encoder = new TextEncoder();
const data = encoder.encode(verifier);
const digest = await crypto.subtle.digest("SHA-256", data);
return base64UrlEncode(new Uint8Array(digest));
}
const codeVerifier = generateCodeVerifier();
const codeChallenge = await generateCodeChallenge(codeVerifier);
-
Redirect to Authorization URL with PKCE
const authUrl = new URL("https://clerk.coloop.ai/oauth/authorize");
authUrl.searchParams.append("client_id", "your_client_id");
authUrl.searchParams.append("redirect_uri", "your_callback_url");
authUrl.searchParams.append("response_type", "code");
authUrl.searchParams.append("scope", "email profile");
authUrl.searchParams.append("code_challenge", codeChallenge);
authUrl.searchParams.append("code_challenge_method", "S256");
// Redirect user to authUrl
-
Exchange Code for Tokens
const response = await fetch("https://clerk.coloop.ai/oauth/token", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: new URLSearchParams({
grant_type: "authorization_code",
client_id: "your_client_id",
code: "authorization_code_from_callback",
code_verifier: codeVerifier,
redirect_uri: "your_callback_url"
})
});
const tokens = await response.json();
Using the Access Token
For both flows, use the access token to make authenticated requests:
const userInfo = await fetch("https://clerk.coloop.ai/oauth/userinfo", {
headers: {
"Authorization": `Bearer ${access_token}`
}
});
const user = await userInfo.json();
// {
// "email": "user@example.com",
// "email_verified": true,
// "name": "John Doe",
// ...
// }
Token Refresh
When the access token expires (after 2 hours), use the refresh token to get a new one:
const response = await fetch("https://clerk.coloop.ai/oauth/token", {
method: "POST",
headers: {
"Content-Type": "application/x-www-form-urlencoded",
},
body: new URLSearchParams({
grant_type: "refresh_token",
client_id: "your_client_id",
refresh_token: "your_refresh_token",
// Include client_secret only for private applications
...(isPrivateApp && { client_secret: "your_client_secret" })
})
});
const tokens = await response.json();
Security Considerations
- Token Storage
- Store access tokens and refresh tokens securely
- For public applications, use secure browser storage mechanisms
- For private applications, use server-side secure storage
- PKCE Verifier
- Generate a new code verifier for each authorization request
- Store the verifier securely until the token exchange
- Error Handling
- Handle token expiration and refresh scenarios gracefully
- Implement retry logic with exponential backoff for failed requests