IDaaS uses the OpenID Connect (OIDC) authorization code flow to implement single sign-on (SSO) for your custom applications. Your application interacts with two endpoints — the authorization endpoint and the token endpoint — to complete the full SSO flow. IDaaS hosts the entire authentication process; your application only needs to handle the result.
How it works
The following steps summarize the OIDC authorization code flow between your application, the user's browser, and IDaaS:
Your application redirects the browser to the IDaaS authorization endpoint.
IDaaS presents the sign-in page. The user authenticates.
IDaaS redirects the browser back to your
redirect_uriwith an authorizationcode.Your application exchanges the
codefor tokens by calling the IDaaS token endpoint.Your application verifies the ID Token and establishes the user's session.
OIDC 1.0 adds a user identity layer on top of OAuth 2.0 and is backward-compatible with the OAuth 2.0 authorization code flow. The key difference is that the token endpoint also returns an ID Token containing user identity claims.
Prerequisites
Before you begin, ensure that you have:
An IDaaS instance
A custom application or OIDC-based application created in IDaaS (see Custom applications)
The
client_idandclient_secretfor your application (available on the General tab of the Applications page)
Integrate SSO with OIDC
Step 1: Get your application credentials
On the Applications page, click your application and open the General tab. Note the client_id and client_secret — these are required for all subsequent API requests.
To rotate or manage credentials, see General configurations.
Step 2: Send a request to the authorization endpoint
When a user accesses your application without an active session, redirect the browser to the IDaaS authorization endpoint with the following parameters.
Find the authorization endpoint URL on the Applications page: click your application, open the Sign-In tab, and look in the Application Settings section.
Construct the redirect URL as follows:
{{Authorization Endpoint}}?
client_id=app_***&
redirect_uri=http%3A%2F%2Flocalhost%3A3000%2F***&
response_type=code&
scope=openid&
state=525f49cc-***| Parameter | Required | Example | Description |
|---|---|---|---|
client_id | Yes | app_michs7r****6pye | The client ID from the General tab. |
scope | Yes | openid email profile | Controls which user attributes are returned. Default for custom applications: openid email profile. OIDC-based applications can also request phone. See Scope and field mapping. |
response_type | Yes | code | Must be code to use the authorization code flow. |
redirect_uri | Yes | http://localhost:3000/user/oauth2/aliyunidaas/callback | The URL where IDaaS sends the authorization code after the user signs in. |
state | No (recommended) | 525f49cc-87c4-4655-b79c-4c4f971b1ad1 | A random string you generate. IDaaS returns this value unchanged. Use it to verify the response comes from the same session and prevent Cross-Site Request Forgery (CSRF) attacks. Use at least 32 characters. |
Always validate the state value when IDaaS redirects back to your application. Reject any response where the returned state does not match the value you sent.
Step 3: Handle the sign-in callback
After the user authenticates, IDaaS performs a 302 redirect to your redirect_uri:
{{redirect_uri}}?
code=CO***&
state=525f49cc-***| Parameter | Example | Description |
|---|---|---|
code | COE59pkCTm4A9nmowJUsfsfarGEaiShj3TuDc7NCzLCYu9 | The authorization code. Use it in the next step to request tokens. |
state | 525f49cc-87c4-4655-b79c-4c4f971b1ad1 | Verify this value matches the one you sent in Step 2 before proceeding. |
IDaaS supports multiple authentication methods, including DingTalk QR code and SMS. See General configuration for the full list.
Step 4: Exchange the authorization code for tokens
After validating the state value, exchange the authorization code for tokens by sending a POST request to the token endpoint. Find the token endpoint URL in the same Application Settings section as the authorization endpoint.
POST /v2/<instance_id>/<app_id>/oauth2/token HTTP/1.0
Host: eiam-api-cn-hangzhou.aliyuncs.com
Content-Type: application/x-www-form-urlencoded
grant_type=authorization_code
&code=n0esc3N*****5acc3f0ogp4
&client_id=s6BhdR*****kqt3
&client_secret=7Fjfp0ZBr1*****KtDRbnfVdmIw
&redirect_uri=http%3A%2F%2Fwww.example.com%2Fsso%2FcallbackA successful response contains both an access token and an ID Token:
{
"token_type": "Bearer",
"access_token": "ATM4SoVDqWgUq***********wk3ZS5mtn6fcSp8NH8",
"expires_in": 1200,
"expires_at": 1644843164,
"id_token": "eyJraWQiOiJLRVkyV************gRIadj-frOIRFChA"
}The user attributes available in the tokens are determined by the scope values you requested in Step 2.
To establish the user's session, use one of the following approaches:
Parse the ID Token — Decode and verify the
id_tokenJWT, then extract the user identity from its claims. See Step 5: Parse and verify the ID Token.Call the UserInfo endpoint — Use the
access_tokento call the UserInfo endpoint and retrieve user attributes. See Step 6: Get user information from the UserInfo endpoint.
Step 5: Parse and verify the ID Token
The ID Token is a JSON Web Token (JWT) signed with RS256. It contains user identity claims in plaintext, plus a Signature that you must verify before trusting the contents.
Signature verification is mandatory. Do not use the claims in an ID Token without first verifying its signature.
To inspect the raw token structure, paste the id_token value into jwt.io. A decoded token looks like this:
{
"kid": "KEY2Ty1qL6u21NGKmccv3jwfd2ndmgtQPnag",
"alg": "RS256"
}.{
"sub": "user_uyvefotjn7kpbejfmxoos3rtmm",
"jti": "jwt_aaaac7xyhclac6aqkgtjaxsthw5yotn5d77pmki",
"iss": "https://pre-eiam-api-cn-hangzhou.aliyun-inc.com/v2/********/oidc",
"iat": 1644841965,
"nbf": 1644841965,
"exp": 1644842265,
"aud": "app_mhylgo3iairjqjdx5eop6uaf34",
"at_hash": "XHEaGpMooM9zvQXaMzCNEA",
"name": "testuser",
"preferred_username": "testuser"
}.[Signature]Get the public key for signature verification
Before verifying the signature, retrieve the JSON Web Key (JWK) public key from IDaaS. Find the public key endpoint URL in Application Settings (same location as the other endpoints).
Calling the endpoint returns a key set:
{
"keys": [
{
"kty": "RSA",
"e": "AQAB",
"use": "sig",
"kid": "KEYkYnc55G********CTvT7So44RGDYdbfs",
"n": "pXmYkIpy1vaNjTMclU86BQjfmDhjlqMAX8ySVvh9gO-nae4ayvG_*********-v4gP27T7u6bUy0GXTlh3eKE0v1LYB81nfqjF2uazlPwPR5yYOhhWcK-gMNByLfE3CnkDc1YGwA3dZmIz-ZjOCKy8xLaBuqjrvwn5tpMpAoYEEaH4jIm7unTdhbKEKspNR-UXKD8q9RppMh5Tn2sB6oPHlQANudJDgqSwEOevIrdmHU0Zqxrb9cscGH9hH0QjmYEu72yI8BVeliPo3jK6JIoqCIcj5K_t8BJlFQ9QLJ8_o9tmd3BFv5_LVsh4BKGw"
}
]
}Verify the signature
Use a JWT library from the jwt.io library list to parse and verify the ID Token. The following example uses the Java library org.bitbucket.b_c:jose4j.
Add the Maven dependency:
<dependency>
<groupId>org.bitbucket.b_c</groupId>
<artifactId>jose4j</artifactId>
<version>0.7.12</version>
</dependency>Replace issuer, appId, jwkJson, and jwt with the actual values from your IDaaS application before running:
import org.jose4j.jwk.JsonWebKey;
import org.jose4j.jwk.JsonWebKeySet;
import org.jose4j.jwt.JwtClaims;
import org.jose4j.jwt.consumer.JwtConsumer;
import org.jose4j.jwt.consumer.JwtConsumerBuilder;
public class IdTokenTest {
public static void main(String[] args) throws Exception {
// EIAM's Issuer identifier (OIDC issuer URL)
String issuer = "https://eiam-api-cn-hangzhou.aliyuncs.com/v2/idaas_padyrlux3mphrlsex4uonyqhxu/**********/oidc";
// The unique identifier of the current application (obtained from EIAM)
String appId = "app_mkif4*****pxpzbasqmu";
// Application public key in JSON format, used to verify the JWT signature
String jwkJson = "{\n" + " \"keys\": [\n" + " {\n" + " \"kty\": \"RSA\",\n" + " \"e\": \"AQAB\",\n" + " \"use\": \"sig\",\n" + " \"kid\": \"KEY2H82C2at57itnW4onT3p1ySjwH4nirjCk\",\n" + " \"n\": \"w7Jl3fAUJp_9GuxV*****QsOA4lnXR5OD4kF4QbIeBiDiH8_MThrFi9k2MB6YMkSzf5JfIkpAS3JCqZ7k6Wooydp4pzaZNZAk3SGzdsa022RmAT" + "-Iayi4Yj6J9tSdTQCjwh2XkzzsIxA_Hla8rWiQ8Vhw1" +
"-7QArgObfe67nSR7LxD55MFLxk9FU0*****RlGhrQGE_0LUuGWtCJG1r1e6aKquyswfxxAr3Rvj8QGIeJrG0R1Pv8m8d1_5OdULhB7149VqjM6D98WFjab0U2SNv0UlREZXTcS4p-2QNm_1egYRRpJEY_00FZqNSYsmErMGepYhO_61KoGqd8cphWQ\"\n" + " }\n" + " ]\n" + "}";
String jwt = "eyJraWQiOiJLRVkySDgyQzJhdD*****uaXJqQ2siLCJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJ1c2Vy*****lmNjRjZjR3amFrbnBieGpjd3V1IiwianRpIjoiand0X2FhYWFkYWllYTc2eWg1cW0zcm11bnoyeGg0eHd5aTJzZHBoNjR6aSIsImlzcyI6Imh0dHBzOi8vZWlhbS1hcGktY24taGFuZ3pob3UuYWxpeXVuY3MuY29tL3YyL2lkYWFzX3BhZHlybHV4M21waHJsc2V4NHVvbnlxaHh1L2FwcF9ta2lmNGR3bHBlaDZkbnM0cHhwemJhc3FtdS9vaWRjIiwiaWF0IjoxNjUzNjMwMDQxLCJuYmYiOjE2NTM2MzAwNDEsImV4cCI6MTY1MzYzMDM0MSwiYXVkIjoiYXBwX21raWY0ZHdscGVoNmRuczRweHB6YmFzcW11IiwibmFtZSI6InRlc3QiLCJwcmVmZXJyZWRfdXNlcm5hbWUiOiJ0ZXN0IiwidXBkYXRlZF9hdCI6MTY1MzYyODU5MH0.pAsUNB8OkdpIxJMZRfLJ7Pa31tsJyl44a1jVIlvdQxwOtPULAwrFxnB0X3eQx89hUGCdvYWl9FO9o-5kT7L-RER0wJYz9YNKqrVNBnaRwINRZyeYLRVurWMMzODQz-V0ULd9raM1M_i2f_SoWFs1gPFtYh_ijUARHISi7Q3q93ZfAuY8Lq2Nq07QunmDbosvioUd5wJG7WCxW5XXZYDUQe9p5IEYd1MSvnWuTOLbg7rKn0Vm4dNYGWjz1WuoAyCsc_QxOCqpmQ_2czoqPeN-SvPJAQ2CykLk7DSnGpABw1aNrjDidLS9Beqsga9VDCth86sk_0lyTZOaORtUrfVTtQ";
// Parse JWK public key set
JsonWebKeySet jsonWebKeySet = new JsonWebKeySet(jwkJson);
// Create JWT validator
JwtConsumer jwtConsumer = createJwtConsumer(jsonWebKeySet, issuer, appId);
// Execute signature verification and parse claims
JwtClaims jwtClaims = jwtConsumer.processToClaims(jwt);
// Prints the user information from the ID Token
System.out.println(jwtClaims);
}
public static JwtConsumer createJwtConsumer(JsonWebKeySet jsonWebKeySet, String issuer, String appId) {
// Configure JWT validator using builder pattern
final JwtConsumerBuilder jwtConsumerBuilder = new JwtConsumerBuilder();
jwtConsumerBuilder.setExpectedIssuer(issuer);
jwtConsumerBuilder.setRequireIssuedAt();
jwtConsumerBuilder.setRequireExpirationTime();
jwtConsumerBuilder.setAllowedClockSkewInSeconds(60);
jwtConsumerBuilder.setExpectedAudience(appId);
// Set public key resolver (match JWK by kid)
jwtConsumerBuilder.setVerificationKeyResolver((jws, nestingContext) -> {
// Get kid from JWT header
final String signKeyId = jws.getKeyIdHeaderValue();
// Find the matching key in the JWK set
for (JsonWebKey jsonWebKey : jsonWebKeySet.getJsonWebKeys()) {
if (signKeyId.equals(jsonWebKey.getKeyId())) {
return jsonWebKey.getKey();
}
}
throw new RuntimeException("Cannot find verification key: " + signKeyId);
});
return jwtConsumerBuilder.build();
}
}A successful run outputs the verified claims:
JWT Claims Set:{sub=user_dt6kj6yf64cf4wjaknpbxjcwuu,
jti=jwt_aaaadaiea76yh5qm3rmunz2xh4xwyi2sdph64zi,
iss=https://eiam-api-cn-hangzhou.aliyuncs.com/v2/idaas_padyrlux3mphrlsex4uonyqhxu/app_**********/oidc,
iat=1653630041,
nbf=1653630041,
exp=1653630341,
aud=app_**********,
name=test,
preferred_username=test,
updated_at=1653628590
}Step 6: Get user information from the UserInfo endpoint
As an alternative to parsing the ID Token, use the access token to call the UserInfo endpoint. The endpoint follows RFC6750.
Find the UserInfo endpoint URL in Application Settings.
GET /v2/<instance_id>/<app_id>/oauth2/userinfo HTTP/1.0
Host: eiam-api-cn-hangzhou.aliyuncs.com
Authorization: Bearer <AccessToken>Sample response:
{
"sub": "user_dt6kj6yf64cf4wjaknpbxjcwuu",
"name": "test",
"preferred_username": "test",
"updated_at": 1653899948
}The UserInfo endpoint returns the same fields as the ID Token, including any extended claims configured for the application.
Advanced settings
OIDC discovery endpoint
IDaaS supports the OpenID Connect Discovery 1.0 standard. The Issuer URL for an application uses the following format:
https://<idaas-api-domain>/v2/<instance_id>/<application_id>/oidc| Parameter | Description | Example |
|---|---|---|
idaas-api-domain | User portal domain | ******.aliyunidaas.com |
instance_id | Instance ID | idaas_m********r2ed22e6m |
application_id | Application ID | app_m********jy6rbau |
Append /.well-known/openid-configuration to the Issuer URL to get the discovery endpoint. Calling it returns all available endpoints:
| Endpoint | Description |
|---|---|
authorization_endpoint | Authorization endpoint |
token_endpoint | Token endpoint |
userinfo_endpoint | UserInfo endpoint |
revocation_endpoint | Token revocation endpoint |
jwks_uri | JWK public key endpoint |
device_authorization_endpoint | Device authorization endpoint (OIDC-based applications only; custom applications do not currently support device code flow login) |
All endpoint URLs are also available directly in Application Settings.
Scope and field mapping
The following table shows which ID Token claims are returned for each scope value.
| Field | Scope | Description |
|---|---|---|
sub | openid | User ID |
jti | openid | JWT ID (auxiliary) |
iss | openid | Token issuer (auxiliary) |
iat | openid | Token issue time (auxiliary) |
nbf | openid | Token validity start time (auxiliary) |
exp | openid | Token expiration time (auxiliary) |
aud | openid | Application client ID (auxiliary) |
at_hash | openid | Access token hash (auxiliary) |
phone_number | phone | Phone number, e.g., +86 130****5678 |
phone_number_verified | phone | Whether the phone number is verified. Verified by default. |
email | email | Email address, e.g., al***@example.com |
email_verified | email | Whether the email address is verified. Verified by default. |
name | profile | Display name |
preferred_username | profile | Username |
updated_at | profile | Last profile update time |
Token endpoint authentication methods
IDaaS supports four authentication methods for the token endpoint, as specified in the token_endpoint_auth_methods_supported field of the discovery endpoint.
| Method | Description |
|---|---|
none | For public clients. Cannot be used with the client_credentials grant type. |
client_secret_basic | Per RFC 6749. |
client_secret_post | Per RFC 6749. |
client_secret_jwt | Per OpenID Connect Core 1.0. |
The following example shows a token endpoint request using client_secret_basic:
POST /token HTTP/1.0
Host: api.aliyunidaas.com
Authorization: Basic YXBwX21pY2hzN3I0*******cHllOkNTKioqKioq
grant_type=authorization_code&
code=COE59pkCTm4J*******arGEaiShj7NCzLCYu9Client secret rotation
See the secret rotation section in General configurations.
What's next
After completing the basic OIDC integration, you may want to:
Customize the sign-in experience — Configure authentication methods and branding in General configuration.
Manage application credentials — Rotate or update your client secret in General configurations.