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
| 授权类型 | RFC | 用例 |
|---|---|---|
| 授权码 | RFC 6749 §4.1 | 默认;带有后端的Web/移动应用。默认启用。 |
| t隐式 | RFC 6749 §4.2 | 仅前端应用,无后端。 |
| 资源所有者密码 | RFC 6749 §4.3 | 无前端重定向的应用程序;用户凭据直接发送。 |
| 客户端凭证 | RFC 6749 §4.4 | 服务间调用,无需用户参与。 |
| 刷新令牌 | RFC 6749 §6 | 无需重新认证即可续订访问令牌。 |
| 设备授权 | RFC 8628 | 输入受限或无浏览器的设备 |
| 令牌交换 | RFC 8693 | 用现有令牌交换具有不同范围或受众的令牌。 |
| JWT持有者 | RFC 7523 | 使用签名的JWT断言而非客户端密钥进行服务身份验证。 |
| 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.

授权码许可
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(默认) | sub、iss、aud |
| profile | name、displayName、avatar |
| 电子邮件地址 | |
| address | 地址(OIDC 对象在JWT 标准中;请参阅OIDC 地址声明) |
| 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.
-
将用户重定向至:
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.
Let users sign in to your website by scanning a QR code
The same flow lets users who are signed in to your native app sign in to your website by scanning a QR code with the app.
- In the Casdoor admin console, add Device login to the Signin methods of the application, with the rule Login page.
- Turn on Device Code in Grant types.
The sign-in page now shows a QR code next to the form and completes the sign-in on its own once the QR code is approved.
The QR code contains the verification_uri, for example https://<casdoor-host>/login/oauth/device/ra91hy?cancelToken=.... A user who scans it with the camera of a phone opens the URL in the browser, signs in, and approves there. Your app can approve it directly instead, with the access token that it already holds:
-
Take the user code from the path of the URL. In the example, it is
ra91hy. -
Show the user what they are about to sign in to.
-
Send a
POSTrequest tohttps://<casdoor-host>/api/loginwith the headerAuthorization: Bearer <access-token>and the body:{
"application": ApplicationName,
"organization": OrganizationName,
"type": "device",
"userCode": "ra91hy"
}
To reject the sign-in, send userCode and the cancelToken from the same URL as query parameters to https://<casdoor-host>/api/cancel-device-auth.
Device grant with several replicas
By default, Casdoor keeps pending device authorization requests, which map device codes to user codes, in memory. With several replicas of Casdoor, the polling request of the device and the confirmation in the browser can reach different replicas, and the flow then fails intermittently.
To share the requests between replicas, set redisEndpoint in conf/app.conf. Casdoor then stores them in Redis. This is the same option that shares sessions, in the format host:port[,db[,password]], and no further option is needed. If Casdoor can't reach Redis at startup, it logs a warning and uses the in-memory store. See the Configuration reference.
Resource owner password credentials grant
Use this grant only when your application can't redirect the user to Casdoor and collects the username and password itself.
-
Turn on the password grant in Grant types of the application.
-
Send a
POSTrequest to the token endpoint:https://<CASDOOR_HOST>/api/login/oauth/access_tokenWith the body:
{
"grant_type": "password",
"client_id": ClientId,
"client_secret": ClientSecret,
"username": Username,
"password": Password,
} -
Read the tokens from the response:
{
"access_token": "eyJhb...",
"id_token": "eyJhb...",
"refresh_token": "eyJhb...",
"token_type": "Bearer",
"expires_in": 10080,
"scope": "openid"
}
Verification code grant
Use this grant in native apps that sign users in with a phone number or an email address and a one-time code, without opening a browser. It is an extension grant of Casdoor, as allowed by RFC 6749, section 4.5. If the application allows it, an address that has no account yet is signed up in the same step.
-
Turn on Verification Code in Grant types of the application, and add an SMS provider, an email provider, or both to the application.
-
Send the code. Send a
POSTrequest with form data tohttps://<casdoor-host>/api/send-verification-code:Field Value applicationIdadmin/<APPLICATION_NAME>typephoneoremaildestThe phone number or email countryCodeThe region of a phone number, e.g. CNorUS. Not needed for an E.164 number like+8613800000000methodlogincaptchaTypenone, or the captcha type andcaptchaTokenwhen the application's captcha provider asks for one -
Exchange the code for tokens. Send a
POSTrequest tohttps://<casdoor-host>/api/login/oauth/access_token:{
"grant_type": "urn:casdoor:params:oauth:grant-type:verification-code",
"client_id": ClientId,
"username": "+8613800000000",
"code": "123456",
"scope": "openid profile"
}usernameis the phone number or the email address that the code was sent to. For a phone number in the national format, also sendcountry_code.
The grant needs no client secret, so it works from a public client. The response is the same as for the other grants and contains a refresh_token that keeps the user signed in.
Wrong codes count toward the Failed signin limit of the application. Casdoor refuses users who have MFA enabled. Use the authorization code grant for them.