This topic describes how to use the OpenID Connect (OIDC) protocol to integrate custom applications with the single sign-on (SSO) service of IDaaS. This helps developers easily implement SSO features for applications, improving user experience and management efficiency.
Background
IDaaS uses the authorization code mechanism based on the standard OIDC protocol to implement SSO for custom applications of enterprises. Social identity providers (IdPs) such as DingTalk and WeChat use the OAuth protocol to implement QR code-based logon. The OIDC protocol used by IDaaS is an upgraded version of the Open Authorization (OAuth) protocol.
Compatibility with OAuth: The OIDC 1.0 protocol creates a user identity layer on top of the OAuth2.0 protocol. Therefore, the OIDC protocol is compatible with the OAuth2.0 protocol. The OIDC authorization code flow is similar to the OAuth2.0 authorization code flow. The difference is that when OIDC authorization code flow is used, the user information endpoint is standardized, and the id-token of a user is returned from the token endpoint.
How the authorization code flow works
For custom applications, SSO is implemented by using the OIDC authorization code flow.
Your application only needs to interact with IDaaS at the authorization endpoint and token endpoint to complete the main process of SSO.
The logon process is fully hosted by IDaaS. Your application only needs to parse the logon result.
Integrate with SSO
Create a custom (or OIDC protocol) application
You must create a custom application or an OIDC-based application in IDaaS and obtain the application keys. If you have obtained the application keys, skip this step. For more information, see Custom applications to complete the application creation.
In the General tab of the Applications page, you can obtain the client_id and client_secret. This pair of keys is used in the subsequent API requests.
If you want to manage or replace the keys, see the application's General configurations.
Send a request to the authorization endpoint
The following steps need to be handled by the application developer.
When a user attempts to access your application, the application must determine whether a logged-on identity of the user is available.
If you need to log on, you need to send an authorization logon request to IDaaS. You can click your application on the Applications page, find the Sign-In tab, and obtain the authorization endpoint of the application in the Application Settings section.
As shown in the following example, generate a complete authorization request URL based on the authorization endpoint URL and initiate a 302 redirect in the browser.
{{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 obtained in the previous step.
scope
Yes
openid email profile
By default, the value is set to openid email profile for a custom application. This indicates that the application can obtain the ID, username, and email address of the logged-on account. If you use an OIDC-based application, the administrator can also select Phone on the configuration page. For more information about the parameter values the application is authorized to obtain when scope is specified, see 3.2 Mapping between the parameter values accessible to applications and specified scope in this topic.
response_type
Yes
code
The value of this parameter is fixed as code. The value indicates that the authorization code mode is used.
redirect_uri
Yes
http://localhost:3000/user/oauth2/aliyunidaas/callback
The redirect URL of the logon result that is returned by IDaaS to the application after the user logs on to the application. This URL is a relay address for the application to receive IDaaS parameters and can receive the authorization
code.state
No
525f49cc-87c4-4655-b79c-4c4f971b1ad1
A random string generated by the application. We recommend that you set a string with more than 32 characters in length. The state value is returned to the application in a subsequent step. The application verifies whether the state value is the same as the initial value the application sends to the authorization endpoint. This ensures the request comes from the same session to prevent the Cross-Site Request Forgery (XSRF) security vulnerability. We recommended that you set a value for the parameter.
Self-service login
If the request sent to the authorization endpoint is successful, you are redirected to the IDaaS logon page.
You can complete authentication through any configured login method. IDaaS provides a variety of login capabilities with different security levels, including DingTalk QR code login and SMS login. For more information, see General configuration.
After successful login, the browser will perform a 302 redirect back to the redirect_uri specified by the application, with code and state parameters in the URL parameters.
Examples:
{{redirect_uri}}? code=CO***& state=525f49cc-***Parameter
Example
Description
code
COE59pkCTm4A9nmowJUsfsfarGEaiShj3TuDc7NCzLCYu9
The authorization code. The application uses the authorization code in the request it sends to IDaaS for an access token.
state
525f49cc-87c4-4655-b79c-4c4f971b1ad1
Ensure that the
statevalue received by the application is the same as the initial value the application sends to the authorization endpoint.Send a request to the token endpoint
After the application receives the authorization code in the previous step, it uses the authorization code to send a POST request to the token endpoint.
Similar to the authorization endpoint mentioned above, You can click your application on the Applications page, find the Sign-In tab, and obtain the token endpoint in the Application Settings section.
Sample request:
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%2FcallbackSample response:
{ "token_type": "Bearer", "access_token": "ATM4SoVDqWgUq***********wk3ZS5mtn6fcSp8NH8", "expires_in": 1200, "expires_at": 1644843164, "id_token": "eyJraWQiOiJLRVkyV************gRIadj-frOIRFChA" }At this point, your user has successfully completed the login. You can choose one of the following two methods to further obtain the current login identity information and create the application-side login state:
Use the id_token in the response result, and after verification, directly obtain the user identity.
Use the access_token in the response result to call the IDaaS user endpoint to obtain the current logged-in user information.
Please refer to the following sections for specific methods.
ImportantThe range of user data that can be obtained is specified by the scope parameter in the first step of the authorization endpoint request.
Parse id_token programmatically
id_tokenis a signed token containing identity information (in JWT format). The id_token issued by IDaaS contains user data that is visible in plaintext when decoded, along with a Signature.To help you understand, you can paste the complete
id_tokencontent into the JWT decoding website to view its contents.The following sample code provides an example:
{ "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]Before using the contents for application login, you need to verify the [Signature] to ensure that the token is issued by IDaaS and not by any third party, to ensure the security of the login. This security measure is mandatory.
Obtain the signature verification public key
Before performing signature verification, you need to first obtain the signature verification public key endpoint published by IDaaS.
Click your application on the Applications page, find the Sign-In tab, and obtain the public key endpoint in the Application Settings section.
The application can obtain the current public key information by accessing this endpoint. You can also open this address directly in a browser to display the public key information.
See the following example:
{ "keys": [ { "kty": "RSA", "e": "AQAB", "use": "sig", "kid": "KEYkYnc55G********CTvT7So44RGDYdbfs", "n": "pXmYkIpy1vaNjTMclU86BQjfmDhjlqMAX8ySVvh9gO-nae4ayvG_*********-v4gP27T7u6bUy0GXTlh3eKE0v1LYB81nfqjF2uazlPwPR5yYOhhWcK-gMNByLfE3CnkDc1YGwA3dZmIz-ZjOCKy8xLaBuqjrvwn5tpMpAoYEEaH4jIm7unTdhbKEKspNR-UXKD8q9RppMh5Tn2sB6oPHlQANudJDgqSwEOevIrdmHU0Zqxrb9cscGH9hH0QjmYEu72yI8BVeliPo3jK6JIoqCIcj5K_t8BJlFQ9QLJ8_o9tmd3BFv5_LVsh4BKGw" } ] }Now you can complete the signature verification and obtain the content in
id_token.Verify signature and login
You can find the corresponding language tool in the JWT official library list and use the tool in your code to verify and parse the
id_token.The following example uses the Java library: org.bitbucket.b_c:jose4j.
First, add the corresponding Maven dependencies:
<dependency> <groupId>org.bitbucket.b_c</groupId> <artifactId>jose4j</artifactId> <version>0.7.12</version> </dependency>The following code provides an example:
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"; // Please set the application public key for parsing as follows (JSON format, used to verify 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); // Signature verification is complete. The user information contained in id_token is output. System.out.println(jwtClaims); } // The method used by the signature verification tool public static JwtConsumer createJwtConsumer(JsonWebKeySet jsonWebKeySet, String issuer, String appId) { // Configure JWT validator using builder pattern final JwtConsumerBuilder jwtConsumerBuilder = new JwtConsumerBuilder(); // Required field configuration 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(); // Traverse JWK collection to find matching key for (JsonWebKey jsonWebKey: jsonWebKeySet.getJsonWebKeys()) { if (signKeyId.equals(jsonWebKey.getKeyId())) { return jsonWebKey.getKey(); } } throw new RuntimeException("Cannot find verification key: " + signKeyId); }); // Build validator instance return jwtConsumerBuilder.build(); } }ImportantPlease replace the issuer, appId, jwkJson, and jwt parts in the code with the actual information you obtained from EIAM.
Sample output:
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 }In this way, the application obtains the identity information of the logged-on user in IDaaS and uses the information for logon.
Obtain user information through the UserInfo endpoint
You can also obtain user information from the UserInfo endpoint.
Click your application on the Applications page, find the Sign-In tab, and obtain the UserInfo endpoint in the Application Settings section.
The request for user information uses the standard RFC6750. Sample request:
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 }NoteThe characters returned by the UserInfo endpoint are consistent with the parameters in id_token. This means that the parameters configured in extended id_token are also returned from the UserInfo endpoint.
Advanced settings
If you have an in-depth understanding of the OIDC protocol, you may use the following concepts or capabilities.
OIDC discovery endpoint
The
issuerof an OIDC-based application is the unique identifier of the token issuer (IDaaS). It uses the following format:https://<idaas-api-domain>/v2/<instance_id>/<application_id>/oidcThe following table describes the parameters in the angle brackets:
Parameter
Description
Example
idaas-api-domain
User portal URL
https://******.aliyunidaas.com
instance_id
Instance ID
idaas_m********r2ed22e6m
application_id
Application ID
app_m********jy6rbau
IDaaS supports the OpenID Connect Discovery 1.0 standard. Adding
/.well-known/openid-configurationafter theissuergives you the OIDC discovery endpoint address for the application.You can discover the following endpoint information by sending a request to the discovery endpoint. All request endpoints can be obtained directly from the Application Settings.
Endpoint
Description
authorization_endpoint
Authorization endpoint
device_authorization_endpoint
Device moderequires standard OIDC application support for this feature. Custom applications do not currently support device code flow logintoken_endpoint
Token endpoint
revocation_endpoint
Token revocation endpoint
userinfo_endpoint
UserInfo endpoint
jwks_uri
JWK public key endpoint
Mapping between scope and field permissions
The following table lists the user information in id_token for OIDC-based applications when scope is specified.
Field
scope
Description
sub
openid
The
userIdof the userjti
openid
The token in JWT format. This is an auxiliary parameter.
iss
openid
The
issuerof the JWT. This is an auxiliary parameter.iat
openid
The time when the JWT token was issued. This is an auxiliary parameter.
nbf
openid
The start time of the validity period of the JWT token. This is an auxiliary parameter.
exp
openid
The expiration time of the JWT token. This is an auxiliary parameter.
aud
openid
The ClientID of the application. This is an auxiliary parameter.
at_hash
openid
The hash value of AccessToken. This is an auxiliary parameter.
phone_number
phone
Phone number, such as
+86 130****5678phone_number_verified
phone
Whether the mobile number is verified. By default, the mobile number is verified.
email
email
Email address, such as
al***@example.comemail_verified
email
Whether the email address is verified. By default, the email address is verified.
name
profile
The display name of the user.
preferred_username
profile
The
usernameof the userupdated_at
profile
The time when the profile of the user was last updated.
Authentication methods supported by the token endpoint
According to the OIDC protocol, IDaaS provides flexibility and supports the following four authentication methods.
The field
token_endpoint_auth_methods_supportedreturned in the discovery endpoint specifies the supported authentication methods.Value
Description
none
Used for Public clients. When authenticating using the
noneauthentication method,grant_typecannot beclient_credentialsclient_secret_basic
This authentication method is implemented according to RFC 6749 - The OAuth 2.0 Authorization Framework.
client_secret_post
This authentication method is implemented according to RFC 6749 - The OAuth 2.0 Authorization Framework.
client_secret_jwt
This authentication method is implemented according to OpenID Connect Core 1.0.
After the application receives the authorization code in the previous step and verifies that the request is valid (verifies that the state value is the same as the initial value the application sends to the authorization endpoint when it sends the request), the application uses the authorization code to send a POST request to the token endpoint.
For example, using
client_secret_basic, a sample token endpoint request is:POST /token HTTP/1.0 Host: api.aliyunidaas.com Authorization: Basic YXBwX21pY2hzN3I0*******cHllOkNTKioqKioq grant_type=authorization_code& code=COE59pkCTm4J*******arGEaiShj7NCzLCYu9For more information, see the OIDC Core 1.0 specification.
Application Client Secret rotation
Please refer to the secret rotation section in General configurations.