从零搭建一个IdentityServer——初识OpenIDConnect

  上一篇文章实现了IdentityServer4与Asp.net core Identity的集成,可使用经过identity注册功能添加的用户,以Password的方式获取Access token,可是不管是Client Credentials仍是Password流程它都是OAuth2.0的流程,本篇文章就来先介绍一下关于OpenIDConnect的基本概念和用法。
本文有如下内容:

OpenIDConnect介绍及基本概念

  根据OpenIDConnect的定义简单来讲,OpenIDConnect=(Identity, Authentication)+Oauth2.0(来自: https://openid.net/connect/faq/
另外从下面的回答能够看出OAuth2.0是一个身份验证/受权框架,而OpenID Connect基于这些提供了身份标识功能,身份标识就是“是谁”的 问题。

   至于oidc如何实现的,详情能够查看文档:https://openid.net/specs/openid-connect-core-1_0.html,从文档中能够找到这样几个关键词:ID Token、Authentication、Authentication Request、Authorization Code Flow、Implicit Flow、Hybrid Flow、Response_Type、Authorization Endpoint、Token Endpoint。html

  以及两个表,OIDC身份验证流程表:
  
  OIDC身份验证请求对应的相应类型(Response_Type)表:
  
  还有一个流程图:
   
  从以上关键词能够得到下面的信息:
  • ID Token:是一个包含特定声明(Claim)的jwt,特定的声明指的是身份验证服务器验证终端用户时候产生的供客户端使用的信息,如发行人(issuer)、最终用户标识(sub)、客户端id(aud)、过时时间(exp)、Token的发布时间(iat)、用户身份验证时间(auth_time)等,另外也能够包含其它的声明。ID Token由身份验证服务器(IdentityServer4,OP)颁发,交由客户端(RP)进行验证。
  • Authentication:由IdentityServer4(OP)提供的身份验证(登陆),最终用户经过IdentityServer4(OP)的身份验证(登陆)后,就能够发起Authentication Request,或者说若是在发起Authentication Request时用户未进行身份验证时将重定向到身份验证界面进行身份验证。
  • Authentication Request:向IdentityServer4(OP)的受权终结点发起的,用于获取ID Token、受权码(Authorization Code)甚至是访问Token(Access Token)的请求。
  • Authorization Code Flow、Implicit Flow、Hybrid Flow:Authentication Request的三种不一样请求流程。
  • Response_Type:Authentication Request的参数之一,根据设定该参数来决定使用哪种请求流程。
  • Authorization Endpoint:受权终结点,用于接收Authentication Request。
  • Token Endpoint:令牌终结点,用于接收访问令牌(Access Token)获取请求。
   
  从两个表格能够知道:三种身份验证流程的特性,如各Token从哪一个终结点返回、是否向用户代理(如浏览器)透漏Token、是否支持刷新Token等。三种身份验证流程经过指定Response_Type来决定,如参数值为 code时进行受权码流程Id_token以及id_token token时进行隐式流程,包含 code以及token时为混合流程
   
  流程图能够了解到OpenIDConnect的整个身份验证及受权步骤,而最终具体的实现就直接对应到受权码流程、隐式流程和混合流程。

OIDC受权码流程及实现

  下面以受权码流程为例进行详细解说,首先受权码流程步骤以下:
  
  受权码流程一共有八个步骤,简单来讲就是由客户端向身份验证服务器发起身份验证请求(响应类型为code),身份验证服务器向用户进行身份验证及用户容许和受权操做后,将受权码发送给客户端,客户端经过受权码向身份验证服务器的Token中阶段获取ID和Access Token,而后对ID Token进行验证并获取用户的ID信息。
 
  接下来使用以前建立的IdentityServer来实现基于受权码流程的身份验证与受权。
  上一篇文章已经对IdentityServer添加了用户及Asp.net Core Identity组件的支持,目前无需再进行任何修改,换句话说如今的IdentityServer已经可以颁发ID Token了,完成受权码流程仅须要Client的支持,Client咱们使用以前文章中添加的Web API来演示,把原有的基于Jwt Bearer的身份验证代码注释掉,添加基于cookie以及OIDC的身份验证服务(注:添加OIDC的时候Client信息须要与IdentityServer中数据库一致,而且相应的Client配置的重定向地址须要与该应用程序匹配):
  

   确保“interactive”这个客户端的重定向地址为“应用程序地址/signin-oidc”,这里须要注意的是这个重定向地址其实是客户端(WebApi)经过方法.AddOpenIdConnect添加的用于处理odic身份验证的身份验证处理器:git

  

  而后启动项目,并访问受保护的资源: https://localhost:51001/WeatherForecast
  就会跳转到身份验证服务器的登陆页面:

   注:IdentityServer4的默认登陆地址为/account/login,可是asp.net core Identity生成的登陆页面是/identity/account/login,为了保证正确跳转需加入如下配置:github

  

  下面是登陆页面url信息:web

  能够看到三个参数:
  一、第一个参数是由于客户端向Identity服务器发起身份验证请求(Authentication Request),但因为终端用户还未登陆,因此先跳转登陆页面,当完成登录后将返回/connect/authorize/callback。
  二、第三个参数是响应类型,值为code,表明当前 使用受权码流程
  三、第二个参数重定向uri是完成受权后,将携带受权码重定向的地址,也就是web Api程序的oidc身份验证地址。
  对于受权码流程的八个步骤来讲,它完成了前三个,目前处于终端用户身份验证(未完成-还未输入用户名密码)阶段:
  
  输入用户名密码登陆后,就能够看到受保护的内容了:
  
  这里完成受权码流程的后四个步骤:
   
  这四个步骤都是由 客户端的oidc身份验证处理器完成的(具体实现参见: https://github.com/dotnet/aspnetcore/blob/main/src/Security/Authentication/OpenIdConnect/src/OpenIdConnectHandler.cs)
  整个过程主要是应用程序(Client)和身份验证服务器进行交互并完成,相关的受权码、ID token以及Access Token均“未”发送到浏览器中,因此受权码流程也是最为安全的流程。
  如何在客户端得到相应的Access Token呢?经过HttpContext.GetTokenAsync("token name");便可得到相应的Token:
  ID Token:

  Access Token:数据库

  能够经过HttpContext获取Token的缘由是在添加oidc身份验证服务时,将SaveTokens选项设置为true,当身份验证成功后程序会自动将各种Token存储到AuthenticationProperties中,最终加密写入Cookie里面,因此虽然数据保存在浏览器,但因为加密缘故,因此以前才说他们均“未”发送到浏览器中:
  那么受权码流程最后一步要如何实现呢?这里有两种方法,其一是经过获取access token以后直接在程序中访问身份验证服务器的UserInfo Endpoint获取,另外就是将oidc选项的GetClaimsFromUserInfoEndpoint设置为true便可:
  
  未获取UserInfo的User Claims信息:
  
  获取UserInfo后的User Claims信息,能够看到多了一个name的claim(关于为何只有一个claim后续文章中再进行说明):
  

OIDC隐式流程及实现

  既然最复杂的受权码流程已经可以实现了,那么简单的隐式流程确定没问题,下面就演示一下如何经过隐式流程将token直接获取到浏览器中。
  首先建立一个支持隐式流程的client:
  
   注:数据库中建立client复制已有的数据修改便可,client密码是加密存储的,复制后使用被复制的client密码便可,另外由于须要将token信息发送到浏览器,因此须要将client信息中的“AllowAccessTokenViaBrowser”设置为1。
  将client的信息配置到client应用上:
  
  隐式流程要求响应类型为id_token或id_token及token。
  配置完成后运行程序并携带如下参数,直接访问IdentityServer的受权终结点:
  https://localhost:5001/connect/authorize?response_type=id_token token&scope=openid scope2&client_id=test1&state=22222&redirect_uri= https://localhost:51001/swagger/index.html&nonce=11111
  登陆成功后程序将自动跳转到参数redirect_uri指定的路径,而且携带token及相关信息:
  将整个url格式化后得到如下结果:

小结

  本篇文章介绍了OpenIDConnect的基本概念,并经过已有的IdentitySever程序演示了基于受权码和隐式流程,其中受权码模式是一种较为安全的模式,全部的关键的数据包括受权码以及各种token均在client的后台完成,若是须要能够把相关的token加密后以cookie的方式放到客户端以供后续使用。而隐式模式能够将各种token返回到浏览器中,这种模式能够在单页应用中使用,将token交由js来进行管理并用于受保护资源的访问。
  另外到目前为止咱们能够看到的是IdentityServer或者说IdentityServer4的做用就是校验Client信息、终端用户的用户名密码信息,而后生成受权码以及各种token,而token的验证和使用实际上仍是在Client中进行的。
  最后OIDC是一个身份验证协议,那么身份验证和受权在Asp.net core应用程序中是如何体现的呢?下篇文章就来聊聊这个问题。
 
 
参考:
 
相关文章
相关标签/搜索