.net Identity学习(二)OAuth
Auth是一个第三方认证协议,Identity支持通过一些Nuget扩展,连接MS、Google、Fb等一些社交账号进行认证,依靠的协议就是OAuth。
单单使用的话,倒是不太用了解细节,但是简单熟悉一下,对开发还是有些好处的。
主要参考信息是这里。
20190710更新,参考了这个视频(非常好的介绍),进行了完善。
角色
在OAuth认证中有四个角色:
- Resource Owner:资源的所有人,就是用户了
- Client:客户端,也就是我们的Web应用
- Resource Server:资源服务器,存储、提供用户信息的服务器,也就是这些第三方网站
- Authorization Server:认证服务器,一般来说和Resource Server是一个
抽象流程
前四步是通过与用户和授权服务器交互,获取Token。最后利用Token从资源服务器获取受保护资源。
实际流程根据用户提供的Grant类型不同而有所不同,Grant类型有如下几类:
- Authorization Code: 授权码,服务端应用一般使用这种
- Implicit: 移动端应用使用,授权信息会在用户设备上处理
- Resource Owner Password Credentials: 用户直接提供用户名和密码授权
- Client Credentials: 访问应用程序自己的资源
最常见的就是Authorization Code授权码类型的授权
授权码授权
1. 授权链接
当用户请求第三方登录时,应用程序向用户提供一个链接,重定向到收取服务器上,如下是一个通过Microsoft账户进行登录的重定向链接
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=b118f232-0a52-4c87-af0c-db2bc64bb27a&scope=https%3A%2F%2Fgraph.microsoft.com%2Fuser.read&response_type=code&redirect_uri=https%3A%2F%2Flocalhost%3A44304%2FAccount%2FExternalLogin&state=CfDJ8HAAhg0V3yBJqO6eBHGuP_nXOCZlI78TXhCuYjloVnLGpWQHPMmd4gsKcoHrcdTC3Rb2ukf_8dYfV67dMVGtCvrG4oRtcA6VszC_aQNFi2ioyWnHoabhzd0IrO_CCe4qZM00tZFrXqTzJeNDcXdOVlemAwWwJCvKyP6bxkRCisJCUv46VX4UDiLqY7PNSFlUG4QXljocH-u9oXW1VUPFhbLR_46LiU7sXl0iwbivQxrvV7ZmnT0q5p2vD7mvQAW014j_IBG12J8ji0RoyRk5pIA
注意到其中几个关键的参数:
- client_id:这是应用程序在MS注册后,从MS获取的唯一标识该应用的Id
- response_type:code,这里的code就代表了授权模式是授权码方式,授权服务器在用户同意授权后,会返回一个授权码
- redirect_uri:这是该应用程序处理授权码的地址,认证通过后,授权服务器将用户重定向回该地址
用户访问这个地址,于是被重定向到授权服务器上
2. 用户认证
用户被重定向到授权服务器上,此时会被要求登录他在该服务器上的账户(已经登陆过则不用)。
授权服务器会根据链接中的信息,解析并提示用户想获得他信息的网站是哪个,想获取哪些信息。
用户同意后,授权服务器会根据链接中的redirect_uri将用户重定向到应用网站中,在URL中会携带授权码code
3.应用授权
用户被重定向回应用中,实际是将认证服务器的认证码通过该特定的访问地址,传递给应用程序。
例如微软帐号,我本机测试的一个回调请求(部分字符被我抹掉了):
https://localhost:44304/signin-microsoft?code=M*b1aefca-0c86-e0f2-727*-b7fb45*5*9a2&state=CfDJ8**Ahg0V3yBJqO6eBHGuP_*7Svbapbd2PcA1NVs1K70qRSv*KJNPz21HYu3OZekAJ*gSR3gkPAJ22Y*_AJYj*PKGT_PE695p-*dbp9KGz*ygtYi2B3EQZMuk0*REqKzcmg-KymeTJP6o*AxYl_*_u5n1iawCq5a3ymXPOeRtIujm*c81DQ_gWTyotIz8*rpaZ***0h2DPG_v*tR1pqYkBwXM-VzMsDI3yyYe1_DFC*9Dw7wDuRzcG2*p5er8inC*xseV_NArDaMKzWk*k8x6L1w
可以看到
- 监听地址是signin-microsoft,这也是Identity的Microsoft认证组件的默认监听地址,下一篇会介绍
- code:我们请求的是authorization code, 所以返回信息携带了code
4.请求Access Token
应用将授权码和应用的client_id、client secret发送至授权服务器
client secret:应用在第三方网站注册时获取的应用私钥,秘密保存,通过该私钥,第三方网站可以认定请求来源确实为该应用。
5.回传Access Token
授权服务器结合应用提供的信息,生成该用户的访问标志Access Token,回传给应用。
至此授权过程完成,后续应用可以使用该Token请求该用户相关的信息。
授权码方式的认证针对现在大多数运行在服务器端的应用,也是绝大多数网站提供的一种授权方式。在认证过程中,应用关键的一个信息client secret是在服务器端完成请求的,比较安全。
为何需要Access Token?
这是我一直的一个疑问,而我从油管上的这个视频得到了答案。
在网络中,我们有back channel
和front channel
的概念
- back channel: 服务端的交互,前台不可见,是一种很安全的渠道
- fron channel: 前端(浏览器)与服务器之间的通信通道,可以比较安全,但是在这个通信方式中,用户或者第三方可以通过各种方式获取到通信过程中的数据(通过查看地址栏,查看调试窗口)等等
在这个认证中,authorization code是在front channel
中、也即通过浏览器页面间的重定向来获取的,而code被获取到后,回发给服务器端,服务器用这个code和自己的secret请求access token,这样access token就只会在服务器端存在,前段永远获取不到,是很安全的方式
Implict内部授权
相比授权码模式,implict模式请求时的授权模式为“token”,而不是"code"。
服务器直接返回了access token到客户端,相对来说没有第一种安全,因为前段可以直接获取access token。但是有的纯前段应用可能需要这种方式
Resource Owner Password Credentials用户密码模式
url中的grant_type模式字符串为"password",用户直接提供用户名和密码,应用将用户密码发给服务器,服务器返回Access Token。
这种模式的认证用户直接将自己的第三方账户提供给了应用,一般是系统内部使用这种方式,或者是机器之间交互,需要用户完全信任应用。
Client Credentials客户端认证信息
client_credentials模式,是客户端自己请求第三方服务,调用一些接口的方式。
客户端发送应用注册时获取的client id和client secret,获取自己账户的access token。
除此之外,OAuth允许access token在过期前进行更新,利用refresh_token类型的请求,如:
https://example.com/v2/oauth/token?grant_type=refresh_token&client_id=CLIENT_ID&client_secret=CLIENT_SECRET&refresh_token=REFRESH_TOKEN
总结
以上就是对OAuth认证流程的简单介绍,之后记录一下Identity通过OAuth接入几个第三方应用的方