NET Core Implementation OAuth2.0 Resourceownerpassword and ClientCredentials modes preface
The development of the Licensing Service framework generally uses the OAUTH2.0 authorization framework, while the development of WEBAPI authorization should use the OAUTH2.0 authorization standard, OAuth2.0 authorization Framework Documentation reference: https://tools.ietf.org/html/rfc6749
The. NET Core Development OAuth2 project requires the use of IdentityServer4, which is now in the RC pre-release version, for reference: https://identityserver4.readthedocs.io/en/dev/
IdentityServer4 Source: Https://github.com/IdentityServer
If the. NET Development OAuth2 Project can use Owin, can refer to the example source code: Https://www.asp.net/aspnet/overview/owin-and-katana/owin-oauth-20-authorization-server
Implement Resourceownerpassword and client credentials mode: Authorization server:
Program.cs to the Main method: Call Useurls to set the IP address of the IDENTITYSERVER4 authorization service
1 var host = new Webhostbuilder () 2 . The use of Usekestrel () 3 //identityserver4 requires configuration of USEURLS4 . Useurls ("http://localhost:4537") 5 . Usecontentroot (Directory.GetCurrentDirectory ()) 6 . Useiisintegration () 7 . Usestartup<startup> () 8 . Build ();
In the Startup.cs-->configureservices method:
1 //rsa: Certificate length more than 2048, or throw exception 2 //Configuration Accesstoken Encryption certificate 3 var RSA = new RSACryptoServiceProvider (); 4 // Obtain the encryption certificate from the configuration file 5 RSA. Importcspblob (convert.frombase64string (configuration["signingcredential")); 6 //identityserver4 Authorized service Configuration 7 services . Addidentityserver () 8 . Addsigningcredential (New Rsasecuritykey (RSA)) //Set up encryption certificate 9// . Addtemporarysigningcredential () //The temporary certificate can be used at the time of testing . Addinmemoryscopes (Oauth2config.getscopes ()) . Addinmemoryclients (Oauth2config.getclients ()) //If it is a client credentials mode then no setup validation user is required . Addresourceownervalidator<myuservalidator> ()//user Authentication interface //. Addinmemoryusers (Oauth2config.getusers ()) //Add fixed users to memory ;
Startup.cs---Configure method:
1 //Use IDENTITYSERVER4 's authorized Service 2 app. Useidentityserver ();
Client Configuration
In Startup.cs, set to Memory by Addinmemoryclients (Oauth2config.getclients ()), configure:
1 new Client 2 {3//client_id 4 ClientId = "Pwd_ Client ", 5//allowedgranttypes = new string[] {granttype.clientcredentials},//client credentials mode 6 allowedgranttypes = new string[] {Granttype.resourceownerpassword},//resource Owner password mode 7//client_secret 8 Clientsecrets = 9 {10 New Secret ("Pwd_secret"). Sha256 ())},12//scope13 allowedscopes =14 {"Api1", 16//If you want to have Refreshtoken, you must set: STANDARDSCOPES.OFFLINEACCESS17 If the client credentials mode does not support Refreshtoken, you do not need to set the OFFLINEACCESS18 standards Copes. offlineaccess.name,19},20//accesstokenlifetime = 3600,//accesstoken's OverDuration, in seconds (defaults to 3600 seconds/1 hour)//absoluterefreshtokenlifetime =,//refreshto Ken's maximum expiration time, in seconds. Defaults to 2592000 seconds/30 day22//refreshtokenusage = tokenusage.onetimeonly,//default state, Refresht Oken can only be used once, after use once the old can not be used, can only use the new RefreshToken23//refreshtokenusage = tokenusage.reuse,//reusable Refres Htoken,refreshtoken, of course, can't use 24 if it expires.
Scope settings
In Startup.cs, set to Memory by Addinmemoryscopes (Oauth2config.getscopes ()), configure:
1 public static ienumerable<scope> getscopes () 2 {3 return new List<scope> 4 {5 new Scope 6 {7 Name = "Api1", 8 Description = "My API", 9 },10 //If you want to have Refreshtoken, Then you must set: Standardscopes.offlineaccess11 standardscopes.offlineaccess,12 };13 }
Account Password Verification
Resource Owner password mode requires authentication of the account password (if the client credentials mode does not need to authenticate the account password):
Mode one: Add users to memory, and IdentityServer4 to verify the account and password:
. Addinmemoryusers (Oauth2config.getusers ())
Mode two (recommended): Implement the Iresourceownerpasswordvalidator Interface for verification:
. Addresourceownervalidator<myuservalidator> ()
Implementation of Iresourceownerpasswordvalidator:
1 Public class Myuservalidator:iresourceownerpasswordvalidator 2 {3 public Task Validateasync ( Resourceownerpasswordvalidationcontext context) 4 {5 if (context. UserName = = "Admin" && context. Password = = "123") 6 {7 //Verify Success 8 //Use subject can be used to differentiate user identities on the resource server and so on 9 //Get: Resource server through User.Claims.Where (l = > L.type = = "Sub"). FirstOrDefault (); Get the ten context. Result = new Grantvalidationresult (Subject: "Admin", Authenticationmethod: "Custom") }12 else13 { //validation failed in the context. Result = new Grantvalidationresult (tokenrequesterrors.invalidgrant, "Invalid custom Credential"); }17 Return Task.fromresult (0); }19 }
Set up an encryption certificate
The encryption certificate for RSA is set by the Addsigningcredential method (Note: The default is to use a temporary certificate, that is, addtemporarysigningcredential (), you should not use the temporary certificate anyway, because each time you restart the licensing service, Will regenerate the new temporary certificate), RSA encryption certificate is more than 2048 long, otherwise the service will throw an exception
Startup.cs configuration in the-->configureservices method:
1 //rsa: Certificate length more than 2048, or throw exception 2 //Configuration Accesstoken Encryption certificate 3 var RSA = new RSACryptoServiceProvider (); 4 // Obtain the encryption certificate from the configuration file 5 RSA. Importcspblob (convert.frombase64string (configuration["signingcredential")); 6 services. Addidentityserver () 7 . Addsigningcredential (New Rsasecuritykey (RSA)) //Set up encryption certificate
How to generate an RSA encryption certificate (the generated Privatekey is configured in IdentityServer4 and can be set to a configuration file):
1 using (RSACryptoServiceProvider Provider = new RSACryptoServiceProvider (2048)) 2 {3 // Console.WriteLine (convert.tobase64string (provider. Exportcspblob (false))); PublicKey4 Console.WriteLine (convert.tobase64string (provider. Exportcspblob (True))); PrivateKey5 }
Resource server
Program.cs, Main method:
1 var host = new Webhostbuilder () 2 . The use of Usekestrel () 3 //identityserver4 requires configuration of USEURLS4 . Useurls ("http://localhost:4823") 5 . Usecontentroot (Directory.GetCurrentDirectory ()) 6 . Useiisintegration () 7 . Usestartup<startup> () 8 . Build ();
Startup.cs---Configure the configuration in the method:
Use the IDENTITYSERVER4 Resource service and configure the app. Useidentityserverauthentication (New identityserverauthenticationoptions { authority = "http://localhost : 4537/", ScopeName =" Api1 ", Savetoken = True, additionalscopes = new string[] {" Offline_access "}, // Add extra scope,offline_access for the refresh token to get scope Requirehttpsmetadata = False, });
Set Authorizeattribute on a resource interface (Controller or method) that requires authorization validation:
1 [Authorize]2 [Route ("Api/[controller]")]3 Public class Valuescontroller:controller
Test resource owner password mode test code:
1 public static void Testresourceownerpassword () 2 {3 var client = new Httpclienthepler ("Htt P://localhost:4537/connect/token "); 4 string accesstoken = null, Refreshtoken = NULL; 5//Get Accesstoken 6 client. Postasync (NULL, 7 "grant_type=" + "password" + 8 "&username=" + "admin" + 9 "&password=" + "123" +10 "&client_id=" + "pwd_client" +11 "&client_secre t= "+" Pwd_secret "+12" &scope= "+" Api1 offline_access ",//scope need to be separated by spaces, offline_access for Get Refreshtoke N13 HD = HD. ContentType = new Mediatypeheadervalue ("application/x-www-form-urlencoded"), Rtnval = 15 {var jsonval = jsonconvert.deserializeobject<dynamic> (rtnval); ACC Esstoken = jsonval.access_token;18 Refreshtoken = jsonval.refresh_token;19},20 fault = Console.WriteLine (fault), ex = Console.writ Eline (ex)). Wait (); if (!string. IsNullOrEmpty (Refreshtoken)) 24 {25//use Refreshtoken to get a new ACCESSTOKEN26 client. Postasync (null,27 "grant_type=" + "Refresh_token" +28 "&client_id=" + "pwd_cli Ent "+29" &client_secret= "+" Pwd_secret "+30" &refresh_token= "+ Refresht OKEN,31 HD = HD. ContentType = new Mediatypeheadervalue ("application/x-www-form-urlencoded"), rtnval + = CONSOLE.WR Iteline ("Results after refresh: \ r \ n" + rtnval), fault = Console.WriteLine (fault), 34 ex = Console.WriteLine (ex)). Wait ();}36 PNs if (!string. IsNullOrEmpty (Accesstoken)) 38 {39//access to resource services, Max client. URL = "Http://localhost:4823/api/values"; Getasync (null,42 HD = HD. ADD ("Authorization", "Bearer" + accesstoken), Rtnval + Console.WriteLine ("\ r \ n Access resource service: \ r \ n" + rtnval), fault = Console.WriteLine (fault), $ ex = Console.writ Eline (ex)). Wait (); 46}47}
Client credentials Mode test code:
1 public static void Testclientcredentials () 2 {3 var client = new Httpclienthepler ("HTTP// Localhost:4537/connect/token "); 4 string accesstoken = null; 5//Get Accesstoken 6 client. Postasync (NULL, 7 "grant_type=" + "client_credentials" + 8 "&client_id=" + "Credt_clie NT "+ 9" &client_secret= "+" Credt_secret "+10" &scope= "+" api1 ",//Do not add Offline_ Access, because the client credentials mode does not support Refreshtoken, or it will fail to authorize one of the HD = HD. ContentType = new Mediatypeheadervalue ("application/x-www-form-urlencoded"), Rtnval =>13 {var jsonval = jsonconvert.deserializeobject<dynamic> (rtnval); acce Sstoken = jsonval.access_token;16},17 fault = Console.WriteLine (fault), 18 ex = Console.WriteLine (ex)). Wait (); 19 20 if (!string. IsNullOrEmpty (Accesstoken)) 21 {22//access to resource services at the client. URL = "Http://localhost:4823/api/values"; Getasync (null,25 HD = HD. ADD ("Authorization", "Bearer" + accesstoken), Rtnval + Console.WriteLine ("Access to resource service: \ r \ n" + RT Nval), fault = Console.WriteLine (fault), ex = Console.writelin E (ex)). Wait (); 29}30}
Attention
1.RefreshToken is stored in memory, not as encrypted by the encryption certificate set by the Accesstoken, but instead generates a unique code stored in the authorization service's memory, so the authorization server restarts then these refreshtoken disappear;
2. The resource server first resolves the accesstoken to the authorization server to obtain the configuration data (for example, Access: Http://localhost:4537/.well-known/openid-configuration Gets the configuration, Http://localhost:4537/.well-known/openid-configuration/jwks get Jwks), then the parsing Accesstoken uses the configuration data obtained for the first time, Therefore, if the configuration of the authorization service changes (encryption certificate and so on), then the resource server should be restarted to retrieve the new configuration data;
3. When debugging the IDENTITYSERVER4 framework, you should configure ILogger, because access to the authorization process (such as authorization failure, and so on) is called ILogger for logging, and nlog can be used, for example:
Configured in the Startup.cs-to-configure method: Loggerfactory.addnlog ();//Add Nlog
Source: Http://files.cnblogs.com/files/skig/OAuth2CredentialsAndPassword.zip
Tags: netcore_identityserver4
NET Core implementation of OAuth2.0 Resourceownerpassword and ClientCredentials modes