1. 凭证(客户端)模式 AllowedGrantTypes = GrantTypes.ClientCredentials
应用场景:客户端/服务与服务之间的交互访问资源,token代表客户端的请求,而不是用户,携带客户端注册时候的贫据进行认证,获取token,
使用过程:会向token endpoint发送token请求,并获得代表客户机的access token,客户端通常必须使用token endpoint的Client ID和secret进行身份验证,必须是完全信任的
GET https://oauth.b.com/token? grant_type=client_credentials& client_id=CLIENT_ID& client_secret=CLIENT_SECRET
2. 密码模式(ClientAllowedGrantTypes = GrantTypes.ResourceOwnerPassword)
应用场景:用于当前的APP是专门为服务端设计,客户端输入用户名密码,根据用户名密码进行验证
使用过程:用户名和密码到token endpoint,向资源服务器请求令牌。这是一种“非交互式”授权方法
POST https://oauth.b.com/token? grant_type=password& username=USERNAME& password=PASSWORD& client_id=CLIENT_ID
3. 简化模式(ClientAllowedGrantTypes =GrantTypes.Implicit)
应用场景:SPA应用程序,不能处理token过期,访问A网站,跳转到B授权中心,B授权中心登录,通过回调地址带上授权码,返回A网站
使用过程:用于服务端和SPA应用程序端进行身份认证,要么用于身份身份验证和access token的传输,token都是基于浏览器传输
注意,这里response_type=token,无需传递client secret,传递client_id只是为了验证在auth server配置的redirect_uri是否一致,redirect_uri中如果携带参数,则最好对url编码再作为参数传递过去
GET https://b.com/oauth/authorize? response_type=token& client_id=CLIENT_ID& redirect_uri=CALLBACK_URL& scope=read
GET https://a.com/callback#token=ACCESS_TOKEN
4. 授权码模式(ClientAllowedGrantTypes=GrantTypes.Code)
应用场景:客户端不输入用户名密码。授权服务器来输入用户名密码,返回 授权码给客户端,客户端拿到授权码,访问授权中心获得访问令牌,授权码失效
授权码的原因:客户端不保存用户名密码,客户端没有能力保证用户名密码的安全,跟简化模式有点类似但是在简化模式上面多了一个授权码的概念
大致步骤:
(A)用户访问客户端,客户端将用户导向认证服务器。用户认证服务器的账号密码
(B)用户选择是否给予客户端授权。
(C)假设用户给予授权,认证服务器将用户导向客户端事先指定的"重定向 URI"(redirection URI),同时附上一个授权码。
(D)客户端收到授权码,附上早先的"重定向URI",向认证服务器申请令牌。这一步是在客户端的后台的服务器上完成的,对用户不可见。
(E)认证服务器核对了授权码和重定向URI,确认无误后,向客户端发送访问令牌(access token)和更新令牌(refresh token)
应用详情:
GET
https://b.com/oauth/authorize? response_type=code& client_id=CLIENT_ID& redirect_uri=CALLBACK_URL& scope=read
GET https://a.com/callback?code=AUTHORIZATION_CODE
POST https://b.com/oauth/token? client_id=CLIENT_ID& client_secret=CLIENT_SECRET& grant_type=authorization_code& code=AUTHORIZATION_CODE& redirect_uri=CALLBACK_URL
- A步骤中,向客户端申请认证的URI,包含以下参数:
response_type:表示授权类型,必选项,此处的值固定为"code"
client_id:表示客户端的ID,必选项
redirect_uri:表示重定向URI,可选项
scope:表示申请的权限范围,可选项
state:表示客户端的当前状态,可以指定任意值,认证服务器会原封不动地返回这个值。 - B步骤,用户选择是否给予客户端授权。(很简单用户自己选就行了)
- C步骤,服务器回应客户端的URI,包含以下参数:
code:表示授权码,必选项。该码的有效期应该很短,通常设为10分钟,客户端只能使用该码一次,否则会被授权服务器拒绝。该码与客户端ID和重定向URI,是一一对应关系。
state:如果客户端的请求中包含这个参数,认证服务器的回应也必须一模一样包含这个参数。 - D步骤,客户端向认证服务器申请令牌的HTTP请求,包含以下参数:
grant_type:表示使用的授权模式,必选项,此处的值固定为"authorization_code"。
code:表示上一步获得的授权码,必选项。
redirect_uri:表示重定向URI,必选项,且必须与A步骤中的该参数值保持一致。
client_id:表示客户端ID,必选项。 - E步骤,认证服务器发送的HTTP回复,包含以下参数:
access_token:表示访问令牌,必选项。
token_type:表示令牌类型,该值大小写不敏感,必选项,可以是bearer类型或mac类型。
expires_in:表示过期时间,单位为秒。如果省略该参数,必须其他方式设置过期时间。
refresh_token:表示更新令牌,用来获取下一次的访问令牌,可选项。
scope:表示权限范围,如果与客户端申请的范围一致,此项可省略。
5. 更新令牌
https://b.com/oauth/token? grant_type=refresh_token& client_id=CLIENT_ID& client_secret=CLIENT_SECRET& refresh_token=REFRESH_TOKEN
3. 混合模式(ClientAllowedGrantTypes =GrantTypes.Hybrid)存在于 IdentityServer4
应用场景:用于MVC框架,服务器端 Web 应用程序和原生桌面/移动应用程序
使用过程:Hybrid是由Implicit和Authorization code结合起来的一种授权方式。其中Implicit用于身份认证,ID token被传输到浏览器并在浏览器进行验证;而Authorization code使用反向通道检索token和刷新token
为什么要用身份认证(OIDC):
比如你去酒店开房,是不是需要身份证?来表明你是谁,是那里人,中国人还是外国人,然后才会给你开个房间,给你钥匙 ,这个是授权
需要身份认证,所以在OAuth2的基础是你要做一些事情就是:
1. 定义端点以返回有关用户的属性(用户声明信息)
2. 定义第三方应用程序可以用来向用户请求身份信息的一个或多个范围(比如酒店可以请求用户的身份证,不需要驾照,交警队就需要你的驾照+身份证才能办一些事情)
3. 为处理身份验证和身份时遇到的方案定义其他错误代码和必要的扩展参数,例如何时基于会话超时重新提示用户的凭据,或如何允许用户选择新帐户登录应用程序时 (简而言之就是当你遇到身份证过期,遗失的时候如何处理)
OIDC把识别用户身份的东西叫做ID Token ,使用发行人的私钥签名的JSON有效负载合成的字符串
1. 用户的唯一标识符sub(subject的简称)(类似你的身份证号)
2. 发布令牌的服务器iis的标识符,说白了就是谁发布的这个id令牌(比如身份证中国政府发的,看身份证背面就有哪个派出所发布的)
3. 请求此令牌的客户端标识符aud(简称audience)
4. 令牌的生存周期exp(类似身份证的过期时间)
{ "iss": "https://server.example.com", "sub": "24400320", "aud": "s6BhdRkqt3", "nonce": "n-0S6_WzA2Mj", "exp": 1311281970, "iat": 1311280970, "auth_time": 1311280969, "acr": "urn:mace:incommon:iap:silver" }
一般会重写 IResourceOwnerPasswordValidator 与 IProfileService 接口来验证用户与自定义一些功能
ids4发现文档: http://localhost:5000/.well-known/openid-configuration
{ "issuer": "http://localhost:5000",发行网址,也就是说我们的权限验证站点。 "jwks_uri": "http://localhost:5000/.well-known/openid-configuration/jwks",这个接口获取的是公钥,用于验证jwt的数字签名部分(数字签名由sso维护的私钥生成)用的。 "authorization_endpoint": "http://localhost:5000/connect/authorize",授权服务器的授权端点的URL。 "token_endpoint": "http://localhost:5000/connect/token",获取token的网址 "userinfo_endpoint": "http://localhost:5000/connect/userinfo",根据token获取用户信息 "end_session_endpoint": "http://localhost:5000/connect/endsession",登录注销。 "check_session_iframe": "http://localhost:5000/connect/checksession",客户端对check_session_iframe执行监视,可以获取用户的登出状态。 "revocation_endpoint": "http://localhost:5000/connect/revocation", 这个网址允许撤销访问令牌(仅access tokens 和reference tokens)。它实现了令牌撤销规范(RFC 7009)。 "introspection_endpoint": "http://localhost:5000/connect/introspect", introspection_endpoint是RFC 7662的实现。 它可以用于验证reference tokens(或如果消费者不支持适当的JWT或加密库,则JWTs)。 "frontchannel_logout_supported": true, 可选。基于前端的注销机制。 "frontchannel_logout_session_supported": true,可选。基于session的注销机制。 "backchannel_logout_supported": true, 指示OP支持后端通道注销 "backchannel_logout_session_supported": true, 可选的。指定RP是否需要在注销令牌中包含sid(session ID)声明,以在使用backchannel_logout_uri时用OP标识RP会话。如果省略,默认值为false。 "scopes_supported": [ "api", "offline_access" ], 支持的范围 "claims_supported": [], 支持的claims "grant_types_supported": [ "authorization_code", "client_credentials", "refresh_token", "implicit" ], 授权类型 "response_types_supported": [ "code", "token", "id_token", "id_token token", "code id_token", "code token", "code id_token token" ], 支持的请求方式 "response_modes_supported": [ "form_post", "query", "fragment" ], 传值方式 "token_endpoint_auth_methods_supported": [ "client_secret_basic", "client_secret_post" ], JSON数组,包含此令牌端点支持的客户端身份验证方法列表。 "subject_types_supported": [ "public" ], JSON数组,包含此OP支持的主题标识符类型列表。 有效值是 pairwise 和 public.类型。 更多信息. "id_token_signing_alg_values_supported": [ "RS256" ], "code_challenge_methods_supported": [ "plain", "S256" ] JSON数组,包含此授权服务器支持的PKCE代码方法列表。 }