Pre-knowledge
may need to see a little bit of prep knowledge
OAuth 2.0 not entirely brief: https://www.cnblogs.com/cgzl/p/9221488.html
OpenID Connect Not entirely brief introduction: https://www.cnblogs.com/cgzl/p/9231219.html
Review OAuth 2.0 and OpenID Connectoauth 2.0 vs OpenID Connect role correspondence
Type of client/relying party
OAuth 2.0 vs OpenID Connect Endpoint definition
OAuth 2.0 vs OpenID Connect Main Licensing method/process Comparison
in fact, OpenID Connect is fully compliant with OAuth 2.0 .
OpenID Connect three of processes
This series of articles focuses on the three processes of OpenID connect
The value of the response type of three flow
Hybrid Flow
This article only describes hybrid Flow. And according to its response_type, it is divided into three kinds of situations:
- Response_type=code Id_token
- Response_type=code token
- Response_type=code Id_token Token
Note: In order to indicate a request for the OpenID connect protocol, the scope parameter must contain OpenID.
1. Response_type=code Id_token:
When Reponse_type is this type, the authorization code and ID token are returned from the authorization endpoint release, and then access token and ID token are returned from the token endpoint release:
2. Response_type=code token:
When Reponse_type is this type, the authorization code and access token are returned from the authorization endpoint release, and then access token and ID token are returned from the token endpoint release:
3. Response_type=code Id_token Token:
When Reponse_type is this type, the authorization code and access token and ID token are returned from the authorization endpoint release, and then access token and ID token are returned from the token endpoint release:
Building an Identity Server 4 project
Identity Server 4 is the framework for OpenID Connect and OAuth 2.0, which is primarily prepared for ASP. It has been officially certified by the OpenID Foundation. It's also open source, Https://github.com/IdentityServer/IdentityServer4.
First of all need a ready-made API project, in fact, this article is useless to: Https://github.com/solenovex/Identity-Server-4-Tutorial-Code, in the 00 directory of the connection.
On top of that, I'll continue to build identity Server 4.
Create an ASP. NET Core Web application in this solution:
Because identity Provider is usually not prepared for a client project or API resource, the name of the project is usually independent of the name of the other project. Here I teach it dave.identityprovider.
Then select the empty template and use ASP. NET Core 2.1:
Click OK, after the project is established, install identity Server 4 for the project, I am through NuGet:
The Identity Server 4 is then configured.
Open Dave.identityprovider's Startup.cs and invoke services in Configureservices . Addidentityserver () to register the identity server in a container of ASP. I then called the services. The Adddevelopersigningcredentials () method, which creates a temporary keying material for token signing (but a durable keying material should be used in a production environment):
Then you need to add the resources and the client, according to the official documentation, I add a config class:
Here I first add a getusers () method, which has two end users.
Note the value of the Subjectid property of TestUser, which must be unique within the identity provider.
There is also a claims attribute under each user, and claims contains some information that represents the user.
But how do you get these claims to return through identity tokens?
Claims is closely linked to Scope and is many-to-one. Here I create a method to return to scope:
Here Identityresource maps to the scope of the user information, followed by Apiresource, which maps to the scopes of API resources. Identityresource is some data about the identity of the user, such as username, name, email, etc. Each identity resource has a unique name, you can assign some claims to it, and these claims will be included in the user's identity token (this is only a case). The client needs to use the scope parameter to request access to an identity resource.
The scopes in the OpenID connect protocol can be understood as a predefined set of claims abbreviations.
OpenID Connect has predefined sets of standard scopes or identity resources:
- OpenID, this is a must . It gives the user a unique ID, also called the subject ID. It appears to tell the authorization server client that an OpenID Connect request is being issued. It also requires that the ID Token be returned. If Response_type contains "token" (referring to access token), then ID token is returned in the authorized response with access token; If the Response_type contains "code" (The Authorization Code), then the ID token is returned as part of the token endpoint response.
- profile, this is optional . This scope requests access to the end user's profile, but does not include email, address, and phone, including the claims: name, Family_name, Given_name, Middle_name, Nickname, Preferred_username, profile, picture, website, gender, birthdate, zoneinfo, Locale, and updated_at .
- Email, this is optional . It consists of email and email_verified two claims.
- address, this is optional . It only has an address of one claim.
- phone, this is optional . It includes two claims of Phone_number and phone_number_verified .
The claims of the four scope requests via profile, email, address, phone, if the requested Response_type value contains "token" (refers to access token), Then these claims are returned from the user information endpoint (UserInfo Endpoint). If Response_type does not contain access tokens, then these claims are returned in the ID token.
The Identityresources class in Identity Server 4 has the above 5 predefined scopes.
So the testuser Given_name and Family_name in the above method will return in Id_token.
Finally, you need to define the client:
For the time being, it just returns an empty collection.
This config class first to this, and now also need to modify the startup Configureservices method, the above config inside the configuration are added:
Then modify the Configure method in startup and add the Identityserver to the ASP. NET Core pipeline:
Enable TLS (SSL)
I have directly modified the Launchsettings.json file, which only retains this part.
Then run the program, visit the URL: https://localhost:5001/.well-known/openid-configuration, you will get the following screen to indicate that the identity Server 4 configuration succeeded:
Add UI for Identity Server 4
The UI for Identity Server 4 can be found here: Https://github.com/IdentityServer/IdentityServer4.Quickstart.UI
Depending on the document description, open PowerShell under the Dave.identityprovider project directory to execute this sentence to install the UI:
IEX (New-object System.Net.WebClient). Downloadstring (' Https://raw.githubusercontent.com/IdentityServer/IdentityServer4.Quickstart.UI/release/get.ps1 ‘))
After you install it, you can see the changes to the project file:
But because this set of UI uses ASP. NET Core MVC, I need to configure something.
In startup's configureservices, register MVC:
In the startup configure, use static files and MVC in the pipeline:
Run the program again, the first page is as follows:
Click Discovery document, which is the page that I opened earlier.
ASP. NET Core MVC as a client
Consider the case of ASP. NET Core MVC as a client application first.
ASP. NET Core MVC is a confidential client (confidential), which is a traditional server-side Web application .
It takes a long time to access (long-lived access), so Refresh tokenis required. Then it can use Authorization Code flow or Hybrid flow.
Here hybrid flow is relatively advanced, which allows the client to first obtain an ID token from the authorization endpoint and pass it through the browser (Front-channel) so that we can verify the ID token. If the validation succeeds then the client then opens a back-end channel (Back-channel)to get access tokens from the Token endpoint.
Below is an example of an authentication request given by the OpenID Connect official documentation.
The URI of the first line: "/authorize" is the authorization endpoint (Authorization Endpoint), which is located in the identity provider (identity provider, IDP). This URI can be found in the discovery document described earlier.
The second line Response_type=code Id_token, which determines which hybrid process to take (refer to the above three figures).
The third line is client_id=xxxx, which is the client's identity.
Line four Redirect_uri=https ...., which is the redirect endpoint for the client (redirection Endpoint).
Line five Scope=openid profile email, this is the client requested scopes.
Look at this picture again:
Why do I have to return two times ID token? This is because the request token in step (4) to require client authentication, when the request token is required to provide authorization Code, client ID and client Secret, these Secret are not exposed to the outside world, These things are passed to the token endpoint by the client server through the backend channel. The first-time ID token is returned from the front-end channel (browser).
When this ID token is validated, it proves who the current user is.
The following is a simple comparison between the front and back channels:
Creating an ASP. NET Core MVC Client
Once created, go back to the Identityprovider project and add a client:
Here ClientName is the client name and it appears on the User Consent authorization page. The process selected is hybrid. For the time being, only the OpenID is requested to return the ID Token, and in the Getidentityresources () method I know I support this scope. The authorization code and tokens of this process are passed to the browser URI by jumping, so I need a URI to receive these things, and the URI inside the Redirecturis is the URI that allows the work.
Continue to configure the MVC client below (Official document: https://identityserver4.readthedocs.io/en/release/quickstarts/3_interactive_login.html# creating-an-mvc-client).
In the configureservices of the MVC client startup:
The following text is the official document of the translation.
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear (); This sentence means that we closed the claim type mapping of JWT in order to allow well-known claims.
Doing so ensures that it does not modify any claims returned from the authorization server.
This is done by invoking services. Addauthentication () method to add and configure the identity authentication middleware.
Here we use cookies as the preferred way to authenticate users, while defaultscheme = "cookies", this "cookie" string can be filled in as long as it is consistent with the back. But if there are many applications on the same server, the scheme name cannot be duplicated.
And the Defaultchanllangescheme is set to "OIDC", the name is the same name as the configuration openidconnect behind. When users need to log in, they will use the OpenID connect Scheme.
Then the Addcookie, whose parameters are the previously configured Defaultscheme name, which configures the cookie processor, and lets the application enable cookie-based authentication for our defaultscheme. Once the ID token has been successfully validated and converted to the claims identity, the information will be stored in the encrypted cookie.
The following Addopenidconnect () method adds support for the OpenID connect process, which lets you configure the processor to perform the OpenID connect protocol.
This processor is responsible for creating authentication requests, token requests, and other requests, and is responsible for verifying the ID token.
Its authentication scheme is the previously configured "OIDC", which means that if a part of the client requires authentication, OpenID connect will be triggered as the default (because the previously set Defaultchallengescheme is " OIDC ", as in the name here).
Signinscheme is consistent with the above defaultscheme, which guarantees that the results of successful authentication will be stored in a cookie with the program name "cookies".
Authority is the address of the identity provider.
ClientID and Secret are the same as the values inside the Identityprovider.
Responsetype is the one described earlier.
The scope of the request has OpenID and profile, in fact, the middleware default also includes these scopes, but write more clearly.
Savetokens=true, which means that the tokens obtained from the identity provider is allowed to be stored.
Then configure the pipeline:
Ensure that the middleware is called before Usemvc ().
Also make sure that the listening address is consistent with the client configured in the Identityprovider:
Then I asked for identity authentication for HomeController:
Then I modified the about method, I just wanted to show the token data:
This token comes from a cookie.
Then modify the About page:
The following tests the identity authentication of the MVC client:
Run identity Provider and MVC two programs at the same time, preferably using the console, so that if there are errors, you can easily see the relevant information.
When you visit the home page of MVC, it automatically jumps to the identity provider:
Specific requests can be seen through Chrome's developer tools:
In the identity provider console, you can also see the relevant information:
After you log in to the user, you'll see a page that asks for permission from the user:
Click Yes.
The browser then transfers to the MVC Client, which is viewed through Chrome's tools:
Can see jump back when is to signin-oidc this address, it is I before the identity provider inside the client's Redirecturi.
At the same time, you can see from the console of the identity provider that the MVC client sends a token request to the token endpoint via the backend channel, which the user will not discover:
This process is the same as in the previous illustration, and after the token endpoint is requested to the new ID token, it is validated again, and then it creates the Claims Identity, which is the user.claims in the preceding code.
This authentication credential is stored in an encrypted cookie:
Come to the About menu:
The value of the ID token can be seen at the top.
Sid is SessionID.
Sub is the user's Subjectid
The IDP is local.
We can parse this ID Token in Jwt.io.
After decoding the ID Token:
Here's the content to speak later.
After logging in handy, think about logout.
Add the Logout button to the _layout.cshtml, this part of the official documents are:
Then create the action method:
The first thing to do is to clear the local cookie, which is the same name as the default scheme that was previously configured, and this step is equivalent to logging out of the MVC client.
The function of the latter line of code is to jump back to identity Provider, and then the user can continue to log out of the IDP, that is, the IDP will clear its cookie.
However, after logging out, the user will remain in the identity provider:
Looking at the IDP console, you can see this failure: Invalida post logout URI:
This is because we did not specify a jump URI address after logout when we configured the client.
Go back to the IDP's client configuration there:
Add the Postlogoutredirecturis property, where this value is the default logout after the jump address.
After the operation, the effect is as follows:
Clicking here will return to the MVC client and then immediately jump to the IDP due to permissions issues.
If you want this process to jump automatically, you can change this value in the IDP's Quickstart/account/accountoptions class to true:
Again, the jump is done automatically.
User Information node
Looking at the decoded ID Token, you can see that these claims are included:
There is no additional information about the user except the sub.
We can specify the parameters to request in the ID token to return the user's other claims, but because the ID token is transmitted from the URI, and the browser will have the length of the URI limit, so try to make token smaller, so as to avoid exceeding the limit.
In order to obtain the user's other claims, the client application can use the user information endpoint, which requires the scopes corresponding to access token and related claims.
First, in the MVC client configuration, Getclaimsfromuserinfoendpoit is true, and the profile scope is requested:
Then add the profile scope to the IDP for the MVC client:
Take the action again and return to the About page:
You can see that the corresponding two claims values in profile scope are already out.
Then the ID token to Jwt.io to decode:
You can see that these two claims are not in the ID token, which means they come from the user information endpoint.
What's in the ID token (official documentation: HTTP://OPENID.NET/SPECS/OPENID-CONNECT-CORE-1_0.HTML#IDTOKEN):
A sub is the user's Subjectid, which is the user's identity.
ISS is the issuer of the ID token.
AUD is the target audience for this token, and here is the ClientID of the MVC client.
NBF means that the ID token is not accepted until this time.
Exp is the expiry time of the ID token.
The IAT is the time of this JWT token release.
Auth_time is the time of the original identity authentication.
Amr refers to the method of identity authentication. Here is the PWD, the password.
Nonce, which is the meaning of number only to being used once. It is a string that uses the ID token and the client session association to reduce repeated attacks.
Finally, there are at_hash, in fact, C_hash, which represent access Token hash and code hash, respectively. is the BASE64 encoding of access token and code in some way. They can be used to link access token or authorization code to this ID token.
I'll be here today.
Code in: 01 parts of Https://github.com/solenovex/Identity-Server-4-Tutorial-Code.
Identity Server 4-hybrid FLOW-MVC client Authentication