上一篇文章实现了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。

  以及两个表,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身份验证的身份验证处理器:

  

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

  下面是登录页面url信息:

  可以看到三个参数:
  1、第一个参数是因为客户端向Identity服务器发起身份验证请求(Authentication Request),但由于终端用户还未登录,所以先跳转登录页面,当完成登陆后将返回/connect/authorize/callback。
  2、第三个参数是响应类型,值为code,代表当前使用授权码流程
  3、第二个参数重定向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应用程序中是如何体现的呢?下篇文章就来聊聊这个问题。
 
 
参考:
 

从零搭建一个IdentityServer——初识OpenIDConnect的更多相关文章

  1. 从零搭建一个IdentityServer——目录(更新中...)

    从零搭建一个IdentityServer--项目搭建 从零搭建一个IdentityServer--集成Asp.net core Identity 从零搭建一个IdentityServer--初识Ope ...

  2. 从零搭建一个IdentityServer——聊聊Asp.net core中的身份验证与授权

    OpenIDConnect是一个身份验证服务,而Oauth2.0是一个授权框架,在前面几篇文章里通过IdentityServer4实现了基于Oauth2.0的客户端证书(Client_Credenti ...

  3. 从零搭建一个IdentityServer——会话管理与登出

    在上一篇文章中我们介绍了单页应用是如何使用IdentityServer完成身份验证的,并且在讲到静默登录以及会话监听的时候都提到会话(Session)这一概念,会话指的是用户与系统之间交互过程,反过来 ...

  4. 从零搭建一个IdentityServer——资源与访问控制

    IdentityServer作为授权服务器它的最终目的是用于对资源进行管控,这里所说的资源有两种,其一是API资源,实际上也就是OIDC协议中客户端(RP)所需要访问的一系列受保护的资源(API),授 ...

  5. 从零搭建一个IdentityServer——项目搭建

    本篇文章是基于ASP.NET CORE 5.0以及IdentityServer4的IdentityServer搭建,为什么要从零搭建呢?IdentityServer4本身就有很多模板可以直接生成一个可 ...

  6. 从零搭建一个IdentityServer——集成Asp.net core Identity

    前面的文章使用Asp.net core 5.0以及IdentityServer4搭建了一个基础的验证服务器,并实现了基于客户端证书的Oauth2.0授权流程,以及通过access token访问被保护 ...

  7. 从零搭建一个IdentityServer——单页应用身份验证

    上一篇文章我们介绍了Asp.net core中身份验证的相关内容,并通过下图描述了身份验证及授权的流程: 注:改流程图进行过修改,第三方用户名密码登陆后并不是直接获得code/id_token/acc ...

  8. 从零搭建一个SpringCloud项目之Feign搭建

    从零搭建一个SpringCloud项目之Feign搭建 工程简述 目的:实现trade服务通过feign调用user服务的功能.因为trade服务会用到user里的一些类和接口,所以抽出了其他服务需要 ...

  9. 使用Vue脚手架(vue-cli)从零搭建一个vue项目(包含vue项目结构展示)

    注:在搭建项目之前,请先安装一些全局的工具(如:node,vue-cli等) node安装:去node官网(https://nodejs.org/en/)下载并安装node即可,安装node以后就可以 ...

随机推荐

  1. Mac苹果电脑单片机开发

    1.安装虚拟机 可以阅读往期文章:Mac苹果电脑安装虚拟机 2.在虚拟机上安装CH340驱动,keil4,PZ-ISP, 下载 CH340驱动安装  下载keil4破解及汉化  下载普中科技烧录软件

  2. 这一次,彻底理解XSS攻击

    希望读完本文大家彻底理解XSS攻击,如果读完本文还不清楚,我请你吃饭慢慢告诉你~ 话不多说,我们进入正题. 一.简述 跨站脚本(Cross-site scripting,简称为:CSS, 但这会与层叠 ...

  3. java有关静态代理及动态代理的实现

    引言: 代理是基本的设计模式之一,它为你提供额外的或不同的操作而插入的用来代替实际对象的对象(委托对象).这些对象通常涉及到与实际对象的通信,因此代理通常充当中间人的角色.--JAVA编程思想 相关的 ...

  4. 关于java方法重写

    1.子类的方法与父类中的方法有相同的返回类型,相同的方法名称.相同的参数列表 2.子类方法的访问级别不能低于父类方法的访问级别 3.子类方法抛出的异常范围不能大于父类中方法抛出的异常范围

  5. express框架路由未导出错误:Router.use() requires a middleware function but got a Object

    在路由的文件下加入导出语句 module.exports = router   导入与导出需要一一对应  

  6. Choreographer全解析

    前言 今天继续屏幕刷新机制的知识讲解,上文说到vsync的处理,每一帧UI的绘制前期处理都在Choreographer中实现,那么今天就来看看这个神奇的舞蹈编舞师是怎么将UI变化反应到屏幕上的. 代码 ...

  7. VsCode/Pycharm配合python env 使用

    前言 用惯了vscode,这几天试了一下pycharm,还是回来了. pycharm一个好处就是python env 环境支持的比较好, vscode虽然也支持但是要改一些东西 env的使用查看我的上 ...

  8. 【Java基础】Java8 新特性

    Java8 新特性 Lambda 表达式 Lambda 是一个匿名函数,我们可以把 Lambda 表达式理解为是一段可以传递的代码(将代码像数据一样进行传递).使用它可以写出更简洁.更灵活的代码. L ...

  9. Redis实战篇(一)搭建Redis实例

    今天是Redis实战系列的第一讲,先从如何搭建一个Redis实例开始. 下面介绍如何在Docker.Windows.Linux下安装. Docker下安装 1.查看可用的 Redis 版本 访问 Re ...

  10. leetcode1637-两点之间不包括任何点的最宽垂直面积

    题目 给你 n 个二维平面上的点 points ,其中 points[i] = [xi, yi] ,请你返回两点之间内部不包含任何点的 最宽垂直面积 的宽度. 垂直面积 的定义是固定宽度,而 y 轴上 ...