博客与笔记无法实时同步, 笔记最新链接
定义:OAuth 2.0是一个开放授权标准:允许资源所有者(用户)授权第三方应用访问该用户在某服务上的特定私有资源,但不提供账号密码给第三方应用。
安全提示:授权码和所有令牌必须通过Tsl加密传输。进入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官网中已经不推荐使用)
+----------+ | 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)用户代理(浏览器)将响应参数传递给客户端
定义:它在OAuth2上构建了一个身份层,是一个基于OAuth2协议的身份认证标准协议
+--------+ +--------+ | | | | | |---------(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。
"response_type"参数值 | OIDC授权类型 |
---|---|
code | Authorization Code Flow |
id_token token | Implicit Flow |
code id_token | Hybrid Flow |
定义: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"
不支持刷新令牌、无法访问用户资源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认证保护Api
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.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
原文:https://www.cnblogs.com/lonelyxmas/p/11100223.html