IdentityServer4笔记整理(更新中)

原文: IdentityServer4笔记整理(更新中)

博客与笔记没法实时同步, 笔记最新连接

OAuth 2.0

定义:OAuth 2.0是一个开放受权标准:容许资源全部者(用户)受权第三方应用访问该用户在某服务上的特定私有资源,但不提供帐号密码给第三方应用。
安全提示:受权码和全部令牌必须经过Tsl加密传输。进入OAuth 2.0官网html

OAuth 2.0协议流程图

     +--------+                               +---------------+
     |        |--(A)- Authorization Request ->|   Resource    |
     |        |                               |     Owner     |
     |        |<-(B)-- Authorization Grant ---|               |
     |        |                               +---------------+
     |        |
     |        |                               +---------------+
     |        |--(C)-- Authorization Grant -->| Authorization |
     | Client |                               |     Server    |
     |        |<-(D)----- Access Token -------|               |
     |        |                               +---------------+
     |        |
     |        |                               +---------------+
     |        |--(E)----- Access Token ------>|    Resource   |
     |        |                               |     Server    |
     |        |<-(F)--- Protected Resource ---|               |
     +--------+                               +---------------+
                         (OAuth 2.0协议流程)
    (A)客户端发起受权请求,客户端能够向资源全部者直接发起受权请求,建议的作法是将受权服务器做为中间人,客户端向受权服务器发起受权请求
    (B)客户端收到受权凭证(和具体的受权类型有关)
    (C)客户端经过受权凭证向受权服务器请求访问令牌
    (D)受权服务器验证受权凭证和客户端,若是经过验证,返回给客户端访问令牌
    (E)客户端经过访问令牌向资源服务器发出访问请求
    (F)资源服务器验证访问令牌有效后,返回请求的资源

受权码模式

受权码模式:code的生命周期必须短暂、或者只能单次使用,若是code被屡次使用,受权服务器必须使该code生成的全部令牌失效。访问令牌由client后端保存。前端

     +----------+
     | Resource |
     |   Owner  |
     |          |
     +----------+
          ^
          |
         (B)
     +----|-----+          Client Identifier      +---------------+
     |         -+----(A)-- & Redirection URI ---->|               |
     |  User-   |                                 | Authorization |
     |  Agent  -+----(B)-- User authenticates --->|     Server    |
     |          |                                 |               |
     |         -+----(C)-- Authorization Code ---<|               |
     +-|----|---+                                 +---------------+
       |    |                                         ^      v
      (A)  (C)                                        |      |
       |    |                                         |      |
       ^    v                                         |      |
     +---------+                                      |      |
     |         |>---(D)-- Authorization Code ---------'      |
     |  Client |          & Redirection URI                  |
     |         |                                             |
     |         |<---(E)----- Access Token -------------------'
     +---------+       (w/ Optional Refresh Token)
    (A)客户端引导用户代理(浏览器)到达受权终结点,并携带参数:response_type(code)、client_id、redirect_uri、scope、state
    (B)受权服务器经过用户代理(浏览器)验证资源全部者,并肯定资源全部者是否给予客户端受权
    (C)验证资源全部者成功,而且容许受权,受权服务器将用户代理(浏览器)重定向到redirect_uri,并返回code和受权请求的state
    (D)客户端向受权服务器令牌终结点请求令牌,携带参数:grant_type、code、redirect_uri、client_id、secret(可选)
    (E)受权服务器验证code、client_id、secret是否有效,并验证redirect_uri是否与步骤C中一致,若是验证成功,携带Access Token将用户代理(浏览器)重定向到redirect_uri

简化模式

要点:不支持刷新令牌,访问令牌编码在Url中,因此会有暴露的风险(在Oauth2.0官网中已经不推荐使用)web

     +----------+
     | Resource |
     |  Owner   |
     |          |
     +----------+
          ^
          |
         (B)
     +----|-----+          Client Identifier     +---------------+
     |         -+----(A)-- & Redirection URI --->|               |
     |  User-   |                                | Authorization |
     |  Agent  -|----(B)-- User authenticates -->|     Server    |
     |          |                                |               |
     |          |<---(C)--- Redirection URI ----<|               |
     |          |          with Access Token     +---------------+
     |          |            in Fragment
     |          |                                +---------------+
     |          |----(D)--- Redirection URI ---->|   Web-Hosted  |
     |          |          without Fragment      |     Client    |
     |          |                                |    Resource   |
     |     (F)  |<---(E)------- Script ---------<|               |
     |          |                                +---------------+
     +-|--------+
       |    |
      (A)  (G) Access Token
       |    |
       ^    v
     +---------+
     |         |
     |  Client |
     |         |
     +---------+
    (A)客户端引导用户代理(浏览器)到达受权终结点,并携带参数:response_type(token)、client_id、redirect_uri、scope、state
    (B)受权服务器经过用户代理(浏览器)验证资源全部者,并肯定资源全部者是否给予客户端受权
    (C)验证资源全部者成功,而且容许受权,受权服务器将用户代理(浏览器)重定向到redirect_uri,redirect_uri的URL 锚点(fragment)部分包括了响应参数(以#hash值的方式追加):access_token、token_type、expires_in、scope、state
    (D)用户代理(浏览器)向redirect_uri发出请求,但不包括URL 锚点,用户代理在本地保存了fragment。
    (E)redirect_uri的服务器返回页面给浏览器,该页面须要包含解码fragment的脚本。
    (F)浏览器接收到页面后,执行脚本,将C中的响应参数解码出来
    (G)用户代理(浏览器)将响应参数传递给客户端

OpenID Connect(OIDC)

定义:它在OAuth2上构建了一个身份层,是一个基于OAuth2协议的身份认证标准协议算法

image

OIDC协议流程图

+--------+                                   +--------+
|        |                                   |        |
|        |---------(1) AuthN Request-------->|        |
|        |                                   |        |
|        |  +--------+                       |        |
|        |  |        |                       |        |
|        |  |  End-  |<--(2) AuthN & AuthZ-->|        |
|        |  |  User  |                       |        |
|   RP   |  |        |                       |   OP   |
|        |  +--------+                       |        |
|        |                                   |        |
|        |<--------(3) AuthN Response--------|        |
|        |                                   |        |
|        |---------(4) UserInfo Request----->|        |
|        |                                   |        |
|        |<--------(5) UserInfo Response-----|        |
|        |                                   |        |
+--------+                                   +--------+
EU:End User:一我的类用户。
RP:Relying Party ,用来代指OAuth2中的受信任的客户端,身份认证和受权信息的消费方;
OP:OpenID Provider,有能力提供EU认证的服务(好比OAuth2中的受权服务),用来为RP提供EU的身份认证信息;
ID Token:JWT格式的数据,包含EU身份认证的信息。
UserInfo Endpoint:用户信息接口(受OAuth2保护),当RP使用Access Token访问时,返回受权用户的信息,此接口必须使用HTTPS。
    (1).RP发送一个认证请求给OP;
    (2).OP对EU进行身份认证,而后提供受权;
    (3).OP把ID Token和Access Token(须要的话)返回给RP;
    (4).RP使用Access Token发送一个请求到UserInfo EndPoint;
    (5).UserInfo EndPoint返回EU的Claims。

OIDC在OAuth之上的扩展

  • [ ] Scope:openid(用来区分这是一个OIDC的Authentication请求,而不是OAuth2的Authorization请求)
  • [ ] response_type:id_token,在implicit模式下请求id_token
  • [ ] id_token:身份令牌,是一个受权服务器提供的包含用户信息(由一组Cliams构成以及其余辅助的Cliams)的JWT格式的数据结构
  • [ ] UserInfo Endpoint:经过id_token从用户信息终结点得到一组EU相关的Claims,好比能够将Claims从token移除,避免token过大,只保留sub,经过UserInfo Endpoint查询Claims
"response_type"参数值 OIDC受权类型
code Authorization Code Flow
id_token token Implicit Flow
code id_token Hybrid Flow
  • Authorization Code Flow:从受权终结点返回code,从令牌终结点返回token
  • Implicit Flow:从受权终结点返回全部token
  • Hybrid Flow:id_token返回给前端,access_token在后端保存(access_token的安全性要求比id_token)高

JSON Web Token

定义:JWT是一个定义一种紧凑的,自包含的而且提供防篡改机制的传递数据的方式的标准协议json

JWT格式

JWT由3部分构成:header.payload.signature
在IdSrv中,payload中的键值对根据token类型和受权流程的不一样有所区别
header:
{
  "alg": "RS256",//签名算法
  "kid": "9dcf733a1192a6da053e64c6ee22ff87",
  "typ": "JWT"//token类型
}
payload://须要传递的数据
{
  "nbf": 1556591630,//该jwt在此以前无效
  "exp": 1556595230,//该jwt在此以后无效
  "iss": "http://localhost:7102",//jwt颁发者
  "iat": 1516239022,//jwt颁发时间
  "aud": "http://localhost:7102/resources",//jwt接收者
  "client_id": "jsImplicit",
  "sub": "SubjectId",//用户惟一id
  "auth_time": 1556591629,//受权时间
  "idp": "local",//identityProvider
  "name": "Username",
  "scope": [
    "openid",
    "profile"
  ],
  "amr": [
    "pwd"//authenticationMethod
  ]
}
signature://token生成方使用私匙生成token,token消费方使用用公匙验证token是否被修改过
RSASHA256(
  base64UrlEncode(header) + "." +base64UrlEncode(payload),Public Key,Private Key
  )
expires_in="exp"-"nbf"

IdentityServer4

客户端凭证模式

不支持刷新令牌、没法访问用户资源scope(openid、profile、email等)后端

Request:
    POST /connect/token HTTP/1.1  #请求方式只能为post
    Host: idsrv-server.com
    Content-type: application/x-www-form-urlencoded #参数只能放在body里面
    body:
    {
        grant_type:client_credentials
        client_id:ClientCredentials
        client_secret:iwiaXNzIjoibnVsbCIsImF1ZCI6WyJudWxsL3Jlc291cmNlcyIsIm9yZGVycyJdLCJjbGllbnRfaWQiOiJDb
        scope:orders openid(可选,默认请求全部scope)
    }
Response:
    HTTP/1.1 200 OK
    Content-Type: application/json
    Cache-Control: no-store
    Pragma: no-cache
     
    {
      "access_token":"MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3",
      "token_type":"bearer",
      "expires_in":3600
    }

资源全部者密码模式

用于同一组织下受权浏览器

#请求token
Request:
    POST /connect/token HTTP/1.1
    Host: idsrv-server.com
    Content-type: application/x-www-form-urlencoded
    body:
    {
        grant_type:password
        username:dd
        password:dd
        client_id:eshopOnVue
        scope:orders(可选参数)
    }

#请求刷新令牌:原刷新令牌失效、以前颁发的access_token不受影响(须要实现手动失效)
Request:
    POST /connect/token HTTP/1.1
    Host: idsrv-server.com
    Content-type: application/x-www-form-urlencoded
    body:
    {
        grant_type:refresh_token
        refresh_token:e4364377ec69c8d5c06a49d7b74efbd2a29015ac37e9ede8e17597d348931d32
        client_id:eshopOnVue
    }
Respose:
{
    "id_token": "eyJhbGciO.iJSUzI1NiI.sImtpZCw",
    "access_token": "eyJhb.GciOiJSUz.I1NiIsIm",
    "expires_in": 3600,
    "token_type": "Bearer",
    "refresh_token": "60e7dda6e30473ce6dc0a1656b38c174a74ef73310d"
}
#经过access_token请求用户终结点(须要scope:profile):/connect/userinfo

简化模式

第三方向受权终结点请求受权,受权成功后,经过Url锚点(#)将access_token、id_token传给redirecturl安全

受权码模式

流程分析服务器

1 IdentityServer服务端启用服务
2 MVC项目配置OIDC保护控制器,并设置clent_id等
3 webApi项目配置Bearer认证保护Apicookie

1.访问受IdentityServer OIDC保护的MVC控制器
2.自动重定向到IdentityServer的/connect/authorize,并附带clint信息

IdSrv受权码模式:
Js客户端mgr.signinRedirect()
1.向IdSrv服务器请求/.well-known/openid-configuration 获取IdSrv数据
2.向/connect/authorize发起受权请求,携带如下参数
client_id: js
redirect_uri:登陆成功后跳转的地址
response_type: code
scope:请求的资源权限
state: 2dd196cd7a68402199534d6123791e64
code_challenge: 23kG8msCLc2oHDnTALRTGElqmNAaTADOwUmLMnENFTE
code_challenge_method: S256
3.1.若是验证client信息正确,且携带了idsrv.session和idsrv两个cookie,并已经受权,则跳转到redirect_uri,并携带如下参数给前端页面:
code:受权码
scope:请求的资源权限
state: a656e5bb62024ee48d8267127e46fa68
session_state: YjwA6dW7trE2II5E0ao6h0y2ty4PoiFrV4qZN0XVjvI.46fe4aa153c9d5480e0f61406e35e5ff
3.1.一、在redirect_uri页面,经过Oidc.UserManager({ response_mode: "query" }).signinRedirectCallback(),经过受权码向/connect/token请求token,携带如下参数
client_id: js
code: 725ca140eb5afdbc8f37cda96eeb53550aa4502de462c77d0618eed2353422d4
redirect_uri: http://localhost:5003/callback.html
code_verifier: a6ff87be469a4171bf1bfd43e5310468bf1d196d337244e2a829b0e94fe476bb9fdad37d300048e692c2fe58c734b0b6
grant_type: authorization_code
3.1.2将code、token写入cookie保存,不然下次经过idsrv.session和idsrv两个cookie申请新的受权码,同时再次跳转到初始请求页面
3.2.若是验证client信息,但未受权,则跳转到/Account/Login并携带一个ReturnUrl参数
该参数为/connect/authorize/callback并附带步骤2的全部参数。该参数须要保存并在登陆成功后,跳转到该页面
3.3输入帐号密码,进入自定义验证Api中
3.4验证成功,经过HttpContext.SignInAsync方法为用户颁发加密的用户凭证,将idsrv.session和idsrv两个cookie写入请求头
3.5.在自定义Api中跳转到ReturnUrl
3.6.1若是未配置受权页面,IdSrv服务端将/connect/authorize/callback重定向到redirect_uri,并携带受权码等参数,重复3.1.1
3.6.2若是配置了受权页面,IdSrv服务端将/connect/authorize/callback重定向到受权页面

登出操做:
Js客户端mgr.signoutRedirect()
1.向IdSrv请求/connect/endsession 并携带如下两个参数
id_token_hint:
post_logout_redirect_uri: 登出回调地址
2.重定向到/Account/Logout 并携带生成的logoutId参数
3.在Logout里清除await HttpContext.SignOutAsync() 并跳转到post_logout_redirect_uri
相关文章
相关标签/搜索