OAuth 2.0
Casdoor is an OAuth 2.0 authorization server. This page describes how to get an access token with each grant type, how to verify a token, and how to use it. If you prefer not to call the endpoints yourself, use a Casdoor SDK or a standard OIDC client.
Endpoints
| Endpoint | URL |
|---|---|
| Authorization | https://<casdoor-host>/login/oauth/authorize |
| Token | https://<casdoor-host>/api/login/oauth/access_token |
| Refresh token | https://<casdoor-host>/api/login/oauth/refresh_token |
| Token introspection | https://<casdoor-host>/api/login/oauth/introspect |
| UserInfo | https://<casdoor-host>/api/userinfo |
In the examples, ClientId and ClientSecret are the Client ID and the Client secret of the Casdoor application.
Supported grant types
| Grant Type | RFC | Use Case |
|---|---|---|
| Authorization Code | RFC 6749 §4.1 | Default; web/mobile apps with a backend. Enabled by default. |
| Implicit | RFC 6749 §4.2 | Frontend-only apps without a backend. |
| Resource Owner Password | RFC 6749 §4.3 | Apps with no frontend redirect; user credentials sent directly. |
| Client Credentials | RFC 6749 §4.4 | Service-to-service calls with no user involved. |
| Refresh Token | RFC 6749 §6 | Renew an access token without re-authenticating. |
| Device Authorization | RFC 8628 | Devices with limited input or no browser. |
| Token Exchange | RFC 8693 | Swap an existing token for one with different scope or audience. |
| JWT Bearer | RFC 7523 | Service auth using a signed JWT assertion instead of a client secret. |
| Verification Code | Casdoor extension | Native apps that sign users in (and up) with a code sent by SMS or email. |
The authorization code grant is on by default. Turn on the other grant types in Grant types on the edit page of the application.

Authorization code grant
Use this grant for applications that sign users in through the browser. It is the recommended grant.
-
Redirect the user to the authorization endpoint:
https://<CASDOOR_HOST>/login/oauth/authorize?
client_id=CLIENT_ID&
redirect_uri=REDIRECT_URI&
response_type=code&
scope=openid&
state=STATE -
The user signs in. Casdoor redirects the browser to your redirect URL with an authorization code:
https://REDIRECT_URI?code=CODE&state=STATE -
Exchange the code for tokens. Send a
POSTrequest to the token endpoint:https://<CASDOOR_HOST>/api/login/oauth/access_tokenWith the body:
{
"grant_type": "authorization_code",
"client_id": ClientId,
"client_secret": ClientSecret,
"code": Code,
} -
Read the tokens from the response:
{
"access_token": "eyJhb...",
"id_token": "eyJhb...",
"refresh_token": "eyJhb...",
"token_type": "Bearer",
"expires_in": 10080,
"scope": "openid"
}
Області
Request scopes with the scope parameter of the authorization URL. They determine which user fields the tokens and the UserInfo endpoint return.
| Область застосування | Опис |
|---|---|
| openid (default) | sub, iss, aud |
| profile | name, displayName, avatar |
| email address | |
| address | address (OIDC object in JWT-Standard; see OIDC address claim) |
| phone | номер телефону |
Separate several scopes with %20:
https://<CASDOOR_HOST>/login/oauth/authorize?
client_id=...&
scope=openid%20email
For the claims behind each scope, see the OpenID Connect specification.
PKCE
Casdoor supports Proof Key for Code Exchange (PKCE), which protects the authorization code of public clients such as mobile and single-page applications.
-
Generate a random code verifier of 43 to 128 characters.
-
Compute the code challenge: the Base64-URL-encoded SHA-256 hash of the verifier.
-
Add two parameters to the authorization URL:
&code_challenge_method=S256&code_challenge=YOUR_CHALLENGE -
Add the
code_verifierparameter, with the original verifier, to the token request.
With PKCE, client_secret is optional in the token request. If you send it, it must be correct.
When Casdoor itself signs users in at an external OAuth provider that requires PKCE, such as Twitter or a custom provider with PKCE turned on, Casdoor generates the code verifier for each flow. You don't implement PKCE for that part.
Bind a token to one service
If your application calls several backend services, you can bind a token to one of them, so that a token that was issued for one service can't be used at another. Casdoor supports Resource Indicators (RFC 8707) for this.
-
Add the
resourceparameter, with an absolute URI that identifies the service, to the authorization URL:https://<CASDOOR_HOST>/login/oauth/authorize?
client_id=CLIENT_ID&
redirect_uri=REDIRECT_URI&
response_type=code&
scope=openid&
state=STATE&
resource=https://api.example.com -
Send the same
resourcein the token request:{
"grant_type": "authorization_code",
"client_id": ClientId,
"client_secret": ClientSecret,
"code": Code,
"resource": "https://api.example.com"
}
The aud (audience) claim of the access token is then the resource URI and not the client ID. The service verifies that a token was issued for it by checking aud. The value of resource must be exactly the same in both requests.
Casdoor carries the resource parameter through interactive sign-in. If the user has to enter a password, complete multi-factor authentication (MFA), or use WebAuthn, the parameter survives the redirects.
Skip the sign-in page with a provider hint
To send the user straight to one OAuth provider, without showing the Casdoor sign-in page, add provider_hint=<provider-name> to the authorization URL:
https://<CASDOOR_HOST>/login/oauth/authorize?
client_id=CLIENT_ID&
redirect_uri=REDIRECT_URI&
response_type=code&
scope=openid&
state=STATE&
provider_hint=github
Casdoor then serves a small redirect page, without loading the full frontend, and sends the user to the provider. This shortens the time to the redirect on slow devices and connections.
Sign-up in the authorization flow
A user who creates an account during the authorization flow is redirected to your redirect URL with an authorization code as soon as the sign-up completes, exactly as after a sign-in. Casdoor carries the authorization parameters, such as client_id, response_type, and redirect_uri, through the sign-up. Your application needs no changes for this.
Implicit grant
Use this grant only for applications without a backend. Prefer the authorization code grant with PKCE.
-
Turn on the implicit grant in Grant types of the application.
-
Redirect the user to:
https://<CASDOOR_HOST>/login/oauth/authorize?client_id=CLIENT_ID&redirect_uri=REDIRECT_URI&response_type=token&scope=openid&state=STATE -
After the user signs in, Casdoor redirects the browser to:
https://REDIRECT_URI/#access_token=ACCESS_TOKEN
Casdoor also supports id_token as response_type.
The implicit grant requires a user with a username and a password. Users who were created only through an external provider and have no local password can't use it and receive invalid_grant. Use the authorization code grant for them.
Device grant
Use this grant for devices with limited input or without a browser, such as smart TVs and CLI tools.
- Turn on the device grant in Grant types of the application.
- Send a request to the
device_authorization_endpointfrom the discovery document. - Show the
verification_urifrom the response to the user, as text or as a QR code. - The user opens the URL on another device, enters the user code, and signs in. Casdoor provides the page behind
verification_uri, so you don't build a UI for it. - Meanwhile, the device polls the token endpoint with its
device_codeuntil the user has signed in. See RFC 8628, section 3.4.
You can also offer device login as a sign-in method in the Signin methods table of the application.