IdentityServer4 实现 OpenID Connect 和 OAuth 2.0
2017-01-14 07:49
971 查看
关于OAuth2.0的相关内容,点击查看:ASP.NETWebApiOWIN实现OAuth2.0OpenID是一个去中心化的网上身份认证系统。对于支持OpenID的网站,用户不需要记住像用户名和密码这样的传统验证标记。取而代之的是,他们只需要预先在一个作为OpenID身份提供者(identityprovider,IdP)的网站上注册。OpenID是去中心化的,任何网站都可以使用OpenID来作为用户登录的一种方式,任何网站也都可以作为OpenID身份提供者。OpenID既解决了问题而又不需要依赖于中心性的网站来确认数字身份。OpenID相关基本术语:最终用户(EndUser):想要向某个网站表明身份的人。标识(Identifier):最终用户用以标识其身份的URL或XRI。身份提供者(IdentityProvider,IdP):提供OpenIDURL或XRI注册和验证服务的服务提供者。依赖方(RelyingParty,RP):想要对最终用户的标识进行验证的网站。以上概念来自:https://zh.wikipedia.org/wiki/OpenID针对.NETCore跨平台,微软官方并没有针对OAuth2.0的实现(上面其实是OAuth的授权,所以会有“获得以下权限”提示,如果是OpenID的话,“权限”应该改为“用户信息”。支持OpenID的服务列表:http://openid.net/get-an-openid/OpenID流程图(来自UsingOpenID):
Microsoft.AspNetCore.Authentication.OAuth组件,仅限客户端),IdentityServer4实现了ASP.NETCore下的OpenIDConnect和OAuth2.0,IdentityServer4也是微软基金会成员。阅读目录:OpenID和OAuth的区别客户端模式(ClientCredentials)密码模式(resourceownerpasswordcredentials)简化模式-WithOpenID(implicitgranttype)简化模式-WithOpenID&OAuth(JS客户端调用)混合模式-WithOpenID&OAuth(HybridFlow)ASP.NETCoreIdentityandUsingEntityFrameworkCoreforconfigurationdata开源地址:https://github.com/yuezhongxin/IdentityServer4.Demo
1.OpenID和OAuth的区别
简单概括:OpenID:authentication(认证),用户是谁?OAuth:authorization(授权),用户能做什么?其实,OAuth的密码授权模式和OpenID有些类似,但也不相同,比如用户登录落网选择微博快捷登录方式,大致的区别:OAuth:用户在微博授权页面输入微博的账号和密码,微博验证成功之后,返回access_token,然后落网拿到access_token之后,再去请求微博的用户API,微博授权中心验证access_token,如果验证通过,则返回用户API的请求数据给落网。OpenID:落网可以没有用户的任何实现,落网需要确认一个URL标识(可以是多个),然后用户登录的时候,选择一个URL进行登录(比如微博),跳转到微博OpenID登录页面,用户输入微博的账号和密码,微博验证成功之后,按照用户的选择,返回用户的一些信息。可以看到,OAuth首先需要拿到一个授权(access_token),然后再通过这个授权,去资源服务器(具体的API),获取想要的一些数据,上面示例中,用户API只是资源服务器的一种(可以是视频API、文章API等等),在这个过程中,OAuth最重要的就是获取授权(四种模式),获取到授权之后,你就可以通过这个授权,做授权范围之类的任何事了。而对于OpenID来说,授权和它没任何关系,它只关心的是用户,比如落网,可以不进行用户的任何实现(具体体现就是数据库没有User表),然后使用支持OpenID的服务(比如微博),通过特定的URL标识(可以看作是OpenID标识),然后输入提供服务的账号和密码,返回具体的用户信息,对于落网来说,它关心的是用户信息,仅此而已。2.客户端模式(ClientCredentials)
简单概述:客户端提供ClientId和ClientSecret给认证授权服务,验证如果成功,返回access_token,客户端拿到access_token,访问API资源服务。2.1认证授权服务配置
创建ASP.NETCore站点,Startup配置修改如下:pIdentityServer4中
AddInMemory的相关配置,都是Mock的(代码配置),也可以把这些配置存储在数据库中,这个后面再讲。
AddInMemoryApiResources增加的API资源服务(List集合),也就此认证授权服务所管辖的API资源,比如上面配置的api1,这个会在客户端调用的时候用到,如果不一致,是不允许访问的,另外,Clinet中配置的
AllowedScopes={"api1"},表示此种授权模式允许的API资源集合(前提是需要添加
ApiResource)。配置很简单,我们也可以访问
http://localhost:5000/.well-known/openid-configuration,查看具体的配置信息:
2.2API资源服务配置
API资源服务站点,需要添加程序包:"IdentityServer4.AccessTokenValidation":"1.0.1"添加一个
ValuesController:
[Route("[controller]")] [Authorize]publicclassValuesController:ControllerBase{ [HttpGet] publicIActionResultGet() { returnContent("helloworld"); } }
2.3单元测试
需要添加程序包:"IdentityModel":"2.0.0"单元测试代码:很简单,和我们之前用ASP.NETWebApiOWIN实现OAuth2.0一样,只不过配置和调用简化了很多,因为IdentityServer4替我们做了很多工作。
3.密码模式(resourceownerpasswordcredentials)
简单概述:客户端提供UserName和Password给认证授权服务,验证如果成功,返回access_token,客户端拿到access_token,访问API资源服务。3.1认证授权服务配置
创建ASP.NETCore站点,Startup配置修改如下:publicclassStartup{ publicvoidConfigureServices(IServiceCollectionservices) { //configureidentityserverwithin-memorystores,keys,clientsandscopes services.AddIdentityServer() .AddTemporarySigningCredential() .AddInMemoryApiResources(newList<ApiResource> { newApiResource("api1","MyAPI") }) .AddInMemoryClients(newList<Client> { //resourceownerpasswordgrantclient newClient { ClientId="ro.client", AllowedGrantTypes=GrantTypes.ResourceOwnerPassword, ClientSecrets= { newSecret("secret".Sha256()) }, AllowedScopes={"api1"} } }) .AddTestUsers(newList<TestUser> { newTestUser { SubjectId="1", Username="xishuai", Password="123" } }); } publicvoidConfigure(IApplicationBuilderapp,ILoggerFactoryloggerFactory) { loggerFactory.AddConsole(LogLevel.Debug); app.UseDeveloperExceptionPage(); app.UseIdentityServer(); }}和客户端模式不同的是,
AllowedGrantTypes授权模式改为了
ResourceOwnerPassword,然后增加了测试用户(用来验证用户名和密码),也可以存储在数据库中。
3.2API资源服务配置
API资源服务站点,需要添加程序包:"IdentityServer4.AccessTokenValidation":"1.0.1"添加一个
IdentityController:
[Route("[controller]")][Authorize]publicclassIdentityController:ControllerBase{ [HttpGet] publicIActionResultGet() { returnnewJsonResult(fromcinUser.Claimsselectnew{c.Type,c.Value}); }}
3.3单元测试
需要添加程序包:"IdentityModel":"2.0.0"单元测试代码:
4.简化模式-WithOpenID(implicitgranttype)
简化模式在IdentityServer4中的实现,就是OpenIDConnect。简单概述:客户端确定URL(用户认证服务),登录在用户认证服务,验证成功,返回客户端想要的用户数据,并使此用户为登录状态,可以在客户端进行注销用户。4.1认证授权服务配置
创建ASP.NETCore站点,Startup配置修改如下:AddInMemoryIdentityResources和
AllowedScopes所配置的,是客户端允许访问的用户信息,具体查看:RequestingClaimsusingScopeValuesClientId很重要,必须和客户端一一对应,所以想要使用OpenID认证服务的客户端,需要向提供OpenID认证服务的机构,申请一个ClientId,OpenID认证服务会统一发放一个用户登录的URL。
TestUser中的
Claims配置,其实就是
IdentityServerConstants.StandardScopes.Profile。另外,还有用户登录的一些操作代码,这边就不贴了,可以查看具体的实现:ImplicitServer.Web
4.2客户端服务配置
创建ASP.NETCore站点,添加程序包:"Microsoft.AspNetCore.Authentication.Cookies":"1.0.*","Microsoft.AspNetCore.Authentication.OpenIdConnect":"1.0.*"Startup配置修改如下:
[code]UseOpenIdConnectAuthentication配置中的
Authority,就是OpenID认证服务的URL。[/code]添加一个
HomeController:访问Secure页面,跳转到认证服务地址,进行账号密码登录,Logout用于用户的注销操作。
4.3Web测试
5.简化模式-WithOpenID&OAuth(JS客户端调用)
简单概述:客户端确定URL(用户认证服务),登录在用户认证服务,验证成功,返回客户端想要的用户数据和access_token,并使此用户为登录状态,可以在客户端进行注销用户,客户端可以拿到access_token,去访问授权范围之内的API资源。需要注意的是:因为简化模式,所以access_token是作为URL参数返回的。5.1认证授权服务配置
创建ASP.NETCore站点,Startup配置修改如下:publicclassStartup{ publicvoidConfigureServices(IServiceCollectionservices) { //configureidentityserverwithin-memorystores,keys,clientsandscopes services.AddIdentityServer() .AddTemporarySigningCredential() .AddInMemoryIdentityResources(newList<IdentityResource> { newIdentityResources.OpenId(), newIdentityResources.Profile(), }) .AddInMemoryApiResources(newList<ApiResource> { newApiResource("api1","MyAPI") }) .AddInMemoryClients(newList<Client> { //OpenIDConnectimplicitflowclient(MVC) newClient { ClientId="js", ClientName="JavaScriptClient", AllowedGrantTypes=GrantTypes.Implicit, AllowAccessTokensViaBrowser=true, RedirectUris={"http://localhost:5022/callback.html"}, PostLogoutRedirectUris={"http://localhost:5022/index.html"}, AllowedCorsOrigins={"http://localhost:5022"}, AllowedScopes= { IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.Profile, "api1" } } }) .AddTestUsers(newList<TestUser> { newTestUser { SubjectId="1", Username="xishuai", Password="123", Claims=newList<Claim> { newClaim("name","xishuai"), newClaim("website","http://xishuai.cnblogs.com") } } }); } publicvoidConfigure(IApplicationBuilderapp,ILoggerFactoryloggerFactory) { loggerFactory.AddConsole(LogLevel.Debug); app.UseDeveloperExceptionPage(); app.UseIdentityServer(); }}因为涉及到访问API资源操作,需要需要添加
AddInMemoryApiResources配置,
AllowedScopes也需要添加对应的API资源名称,
AllowAccessTokensViaBrowser=true的配置的作用就是,可以在浏览器地址中访问access_token。更多实现代码,点击查看:ImplicitServerWithJS.Web
5.2API资源服务配置
API资源服务站点,需要添加程序包:"IdentityServer4.AccessTokenValidation":"1.0.1","Microsoft.AspNetCore.Cors":"1.1.0"Startup配置修改如下:因为JS需要跨域访问API资源服务,所以需要增加CORS配置。添加一个
IdentityController:
[Route("[controller]")][Authorize]publicclassIdentityController:ControllerBase{ [HttpGet] publicIActionResultGet() { returnnewJsonResult(fromcinUser.Claimsselectnew{c.Type,c.Value}); }}
5.3JSWeb站点测试
创建一个ASP.NETCore站点,添加oidc-client.js前端组件,测试JS代码:
///<referencepath="oidc-client.js"/>functionlog(){ document.getElementById('results').innerText=''; Array.prototype.forEach.call(arguments,function(msg){ if(msginstanceofError){ msg="Error:"+msg.message; } elseif(typeofmsg!=='string'){ msg=JSON.stringify(msg,null,2); } document.getElementById('results').innerHTML+=msg+'\r\n'; });}document.getElementById("login").addEventListener("click",login,false);document.getElementById("api").addEventListener("click",api,false);document.getElementById("logout").addEventListener("click",logout,false);varconfig={ authority:"http://localhost:5003", client_id:"js", redirect_uri:"http://localhost:5022/callback.html", response_type:"id_tokentoken", scope:"openidprofileapi1", post_logout_redirect_uri:"http://localhost:5022/index.html",}; varmgr=newOidc.UserManager(config);mgr.getUser().then(function(user){ if(user){ log("Userloggedin",user.profile); } else{ log("Usernotloggedin"); }});functionlogin(){ mgr.signinRedirect();}functionapi(){ mgr.getUser().then(function(user){ varurl="http://localhost:5012/identity"; varxhr=newXMLHttpRequest(); xhr.open("GET",url); xhr.onload=function(){ log(xhr.status,JSON.parse(xhr.responseText)); } xhr.setRequestHeader("Authorization","Bearer"+user.access_token); xhr.send(); });}functionlogout(){ mgr.signoutRedirect();}测试过程(注意下URL中的参数):
6.混合模式-WithOpenID&OAuth(HybridFlow)
混合模式(HybridFlow)是一种新的模式,是简化模式(implicitflow)和验证码模式(authorizationcodeflow)的混合。简单概述:客户端确定URL(用户认证服务),登录在用户认证服务,验证成功,返回客户端想要的用户数据和access_token,并使此用户为登录状态,可以在客户端进行注销用户,客户端可以拿到access_token,去访问授权范围之内的API资源。和上面的简化模式流程差不多,不过access_token不是通过浏览器获取的,而是通过后台服务获取。6.1认证授权服务配置
创建ASP.NETCore站点,Startup配置修改如下:AllowedGrantTypes配置改为
HybridAndClientCredentials,
AllowOfflineAccess需要设置为
true。更多实现代码,点击查看:HybridServer.Web
6.2API资源服务配置
API资源服务站点,需要添加程序包:"IdentityServer4.AccessTokenValidation":"1.0.1"Startup配置修改如下:添加一个
IdentityController:
[Route("[controller]")][Authorize]publicclassIdentityController:ControllerBase{ [HttpGet] publicIActionResultGet() { returnnewJsonResult(fromcinUser.Claimsselectnew{c.Type,c.Value}); }}
6.3客户端服务配置
创建ASP.NETCore站点,添加程序包:"Microsoft.AspNetCore.Authentication.Cookies":"1.0.*","Microsoft.AspNetCore.Authentication.OpenIdConnect":"1.0.*","IdentityModel":"2.0.0"Startup配置修改如下:
CallApiUsingClientCredentials是通过客户端模式获取access_token,
CallApiUsingUserAccessToken是通过上下文获取保存的access_token,其实和浏览器URL中获取是一样的意思,但需要配置
SaveTokens=true。
6.4Web测试
7.ASP.NETCoreIdentityandUsingEntityFrameworkCoreforconfigurationdata
使用ASP.NETCoreIdentity,就是用户管理不由OpenID认证服务进行提供,ASP.NETCoreIdentity就相当于用户的一个管理者,比如用户的存储等。我没做这一块的示例,配置比较简单:publicvoidConfigureServices(IServiceCollectionservices){ services.AddDbContext<ApplicationDbContext>(options=> options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); services.AddIdentity<ApplicationUser,IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultTokenProviders(); services.AddMvc(); services.AddTransient<IEmailSender,AuthMessageSender>(); services.AddTransient<ISmsSender,AuthMessageSender>(); //AddsIdentityServer services.AddIdentityServer() .AddTemporarySigningCredential() .AddInMemoryIdentityResources(Config.GetIdentityResources()) .AddInMemoryApiResources(Config.GetApiResources()) .AddInMemoryClients(Config.GetClients()) .AddAspNetIdentity<ApplicationUser>();}详细使用:UsingASP.NETCoreIdentity关于IdentityServer4的配置信息,可以使用EntityFrameworkCore进行存储,配置如下:
publicvoidConfigureServices(IServiceCollectionservices){ services.AddMvc(); varconnectionString=@"server=(localdb)\mssqllocaldb;database=IdentityServer4.Quickstart;trusted_connection=yes"; varmigrationsAssembly=typeof(Startup).GetTypeInfo().Assembly.GetName().Name; //configureidentityserverwithin-memoryusers, //butEFstoresforclientsandresources services.AddIdentityServer() .AddTemporarySigningCredential() .AddTestUsers(Config.GetUsers()) .AddConfigurationStore(builder=> builder.UseSqlServer(connectionString,options=> options.MigrationsAssembly(migrationsAssembly))) .AddOperationalStore(builder=> builder.UseSqlServer(connectionString,options=> options.MigrationsAssembly(migrationsAssembly)));}详细使用:UsingEntityFrameworkCoreforconfigurationdata最后,简要总结下使用IdentityServer4的几种应用场景:客户端模式(ClientCredentials):和用户无关,用于应用程序与API资源的直接交互场景。密码模式(resourceownerpasswordcredentials):和用户有关,一般用于第三方登录。简化模式-WithOpenID(implicitgranttype):仅限OpenID认证服务,用于第三方用户登录及获取用户信息,不包含授权。简化模式-WithOpenID&OAuth(JS客户端调用):包含OpenID认证服务和OAuth授权,但只针对JS调用(URL参数获取),一般用于前端或无线端。混合模式-WithOpenID&OAuth(HybridFlow):推荐使用,包含OpenID认证服务和OAuth授权,但针对的是后端服务调用。开源地址:https://github.com/yuezhongxin/IdentityServer4.Demo参考资料:IdentityServer4IdentityServer4.SamplesWelcometoIdentityServer4WelcometoOpenIDConnectOpenID学习笔记OAuth和OpenID的区别OAuth、OAuth与OpenID区别和联系使用OpenID、OAuth和FacebookConnect武装你的站点OpenIDConnect身份认证标准推出,获谷歌微软支持原文地址:http://www.cnblogs.com/xishuai/p/identityserver4-implement-openid-connect-and-oauth2.html.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注
相关文章推荐
- IdentityServer4 ASP.NET Core的OpenID Connect OAuth 2.0框架学习保护API
- IdentityServer4 ASP.NET Core的OpenID Connect OAuth 2.0框架学习保护API
- IdentityServer4 ASP.NET Core的OpenID Connect OAuth 2.0框架学习保护API
- IdentityServer3——入门教程:.NET开源OpenID Connect 和OAuth解决方案IdentityServer v3 术语
- 基于 IdentityServer3 实现 OAuth 2.0 授权服务数据持久化
- IdentityServer4 实现 OpenID Connect 和 OAuth 2.0
- 基于 IdentityServer3 实现 OAuth 2.0 授权服务【客户端模式(Client Credentials Grant)】
- IdentityServer3——入门教程:.NET开源OpenID Connect 和OAuth解决方案IdentityServer v3 介绍
- 基于 IdentityServer3 实现 OAuth 2.0 授权服务【密码模式(Resource Owner Password Credentials)】
- 【ASP.NET Core分布式项目实战】(一)IdentityServer4登录中心、oauth密码模式identity server4实现
- 一个功能完备的.NET开源OpenID Connect/OAuth 2.0框架——IdentityServer3
- OpenID Connect:OAuth 2.0协议之上的简单身份层
- ASP.NET 中OAUTH 2.0 及OPENID CONNECT的介绍
- 一个功能完备的.NET开源OpenID Connect/OAuth 2.0框架——IdentityServer3
- IdentityServer4 中文文档 -11- (快速入门)添加基于 OpenID Connect 的用户认证
- IdentityServer4 使用OpenID Connect添加用户身份验证
- .NET开源OpenID和OAuth解决方案Thinktecture IdentityServer
- Modern Web Identity: Why Your Web Applications Should Be Offering OpenID, OAuth, And Probably Facebook Connect
- .NET开源OpenID和OAuth解决方案Thinktecture IdentityServer
- Testing WSO2 Identity Server OAuth 2.0 support with Curl