网上有很多关于使用JWT(Json Web Token
)进行身份验证的信息.但是,在多域环境中使用JWT令牌作为单点登录解决方案时,我仍然没有找到明确的解释.
我在一家公司工作,该公司在不同的主机上有很多站点.我们使用example1.com和example2.com.我们需要一个单点登录解决方案,这意味着如果用户在example1.com上进行身份验证,我们希望他也可以自动在example2.com上进行身份验证.
使用OpenId Connect流程,我了解想要在example1.com上进行身份验证的用户将首先被重定向到身份验证服务器(或OP
"OpenId Provider").用户在该服务器上进行身份验证,然后使用签名的JWT令牌将其重定向回原始example1.com站点.(我知道有另一个流程返回一个中间令牌,以后可以将其交换为真正的JWT令牌,但我不认为这对我们来说是必需的)...
所以现在用户回到example1.com并进行身份验证!他可以发出请求,在Authentication
标头中传递JWT令牌,服务器能够验证签名的JWT,因此能够识别用户.太好了!
第一个问题:
如何将JWT令牌存储在客户端上?还有很多关于此的信息,人们似乎同意使用Web Storage
是走的路而不是好的旧路cookies
.我们希望JWT在浏览器重启之间保持一致,所以让我们使用Local Storage
,而不是Session Storage
......
现在用户可以重新启动他的浏览器,只要JWT令牌没有过期,他仍然会在example1.com上进行身份验证!
此外,如果example1.com需要向我们的另一个域发出Ajax请求,我理解配置CORS会允许这样做.但我们的主要用例不是跨域请求,它有一个单点登录解决方案!
因此,主要问题是:
现在,流程应该是什么,如果用户访问example2.com并且我们希望他使用他已经拥有的JWT令牌进行身份验证?Local Storage
似乎不允许跨域访问,所以此时浏览器无法读取JWT令牌以向example2.com发出请求!
应该 :
在OpenID Connect中,访问令牌具有到期时间.对于授权代码流,这通常很短(例如20分钟),之后您使用刷新令牌来请求新的访问令牌.
该ID令牌还具有期满时间.我的问题是这是什么意思?
任何ID令牌到期时间小于刷新令牌的到期时间将意味着您最终将拥有一个过期的ID令牌,但是有效的访问令牌.
所以你的意思是:
该ID连接规范只是说,验证一个ID令牌时,
"The current time MUST be before the time represented by the exp Claim."
Run Code Online (Sandbox Code Playgroud)
哪(可能)支持上面的第三个选项.
编辑
由于OpenID Connect建立在OAuth2上,因此可以在OAuth2规范中找到以下补充问题的答案,该规范说,
expires_in
RECOMMENDED. The lifetime in seconds of the access token.
Run Code Online (Sandbox Code Playgroud)
一个相关的问题是当您为令牌交换授权代码时,相同的规范说您可能会收到如下响应:
{
"access_token": "SlAV32hkKG",
"token_type": "Bearer",
"refresh_token": "8xLOxBtZp8",
"expires_in": 3600,
"id_token": "eyJhbG[...]"
}
Run Code Online (Sandbox Code Playgroud)
但是在这种情况下,"expires_in"与什么有关?访问令牌,刷新令牌或ID令牌?
(有关信息,IdentityServer3将此设置为访问令牌到期时间).
我试图了解在ASP.NET Core中进行身份验证的正确方法.我看过几个资源(其中大部分都已过时).
有些人提供了使用基于云的解决方案(如Azure AD)或使用IdentityServer4并托管我自己的令牌服务器的替代解决方案.
在早期版本的.Net中,一种更简单的身份验证形式是创建自定义Iprinciple并在其中存储其他身份验证用户数据.
public interface ICustomPrincipal : System.Security.Principal.IPrincipal
{
string FirstName { get; set; }
string LastName { get; set; }
}
public class CustomPrincipal : ICustomPrincipal
{
public IIdentity Identity { get; private set; }
public CustomPrincipal(string username)
{
this.Identity = new GenericIdentity(username);
}
public bool IsInRole(string role)
{
return Identity != null && Identity.IsAuthenticated &&
!string.IsNullOrWhiteSpace(role) && Roles.IsUserInRole(Identity.Name, role);
}
public string FirstName { get; set; }
public string LastName { get; set; …
Run Code Online (Sandbox Code Playgroud) IdentityServer支持在Flows枚举中定义并为客户端设置的不同OpenId Connect流.还有每种类型的流量,并在文档给他们很多的参考样本,但我找不到什么流是一个简单的定义列表的文件,如果他们是太明显言传.但我想他们不是.您能告诉我们这些差异的更多信息,也许我们可以将其添加到文档中吗?
那么什么是:隐式流,资源所有者密码凭证流,授权代码流,客户端凭证流,自定义授权流和混合流?还有哪些是OAuth流,哪些是OpenID Connect流?
谢谢!
openid oauth-2.0 thinktecture-ident-server openid-connect identityserver3
好吧,我明白我问的问题可能很明显,但不幸的是我缺乏关于这个主题的知识,这个任务对我来说似乎很棘手.
我有一个OpenID Connect Provider返回的id令牌(JWT).这里是:
eyJraWQiOiIxZTlnZGs3IiwiYWxnIjoiUlMyNTYifQ.ewogImlzcyI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZfV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5NzAsCiAiY19oYXNoIjogIkxEa3RLZG9RYWszUGswY25YeENsdEEiCn0.XW6uhdrkBgcGx6zVIrCiROpWURs-4goO1sKA4m9jhJIImiGg5muPUcNegx6sSv43c5DSn37sxCRrDZZm4ZPBKKgtYASMcE20SDgvYJdJS0cyuFw7Ijp_7WnIjcrl6B5cmoM6ylCvsLMwkoQAxVublMwH10oAxjzD6NEFsu9nipkszWhsPePf_rM4eMpkmCbTzume-fzZIi5VjdWGGEmzTg32h3jiex-r5WTHbj-u5HL7u_KP3rmbdYNzlzd1xWRYTUs4E8nOTgzAUwvwXkIQhOh5TPcSMBYy6X3E7-_gr9Ue6n4ND7hTFhtjYs3cjNKIA08qm5cpVYFMFMG6PkhzLQ
它的头和有效负载解码如下:
{
"kid":"1e9gdk7",
"alg":"RS256"
}.
{
"iss": "http://server.example.com",
"sub": "248289761001",
"aud": "s6BhdRkqt3",
"nonce": "n-0S6_WzA2Mj",
"exp": 1311281970,
"iat": 1311280970,
"c_hash": "LDktKdoQak3Pk0cnXxCltA"
}
Run Code Online (Sandbox Code Playgroud)
从IODC提供商的发现中,我得到了公钥(JWK):
{
"kty":"RSA",
"kid":"1e9gdk7",
"n":"w7Zdfmece8iaB0kiTY8pCtiBtzbptJmP28nSWwtdjRu0f2GFpajvWE4VhfJAjEsOcwYzay7XGN0b-X84BfC8hmCTOj2b2eHT7NsZegFPKRUQzJ9wW8ipn_aDJWMGDuB1XyqT1E7DYqjUCEOD1b4FLpy_xPn6oV_TYOfQ9fZdbE5HGxJUzekuGcOKqOQ8M7wfYHhHHLxGpQVgL0apWuP2gDDOdTtpuld4D2LK1MZK99s9gaSjRHE8JDb1Z4IGhEcEyzkxswVdPndUWzfvWBBWXWxtSUvQGBRkuy1BHOa4sP6FKjWEeeF7gm7UMs2Nm2QUgNZw6xvEDGaLk4KASdIxRQ",
"e":"AQAB"
}
Run Code Online (Sandbox Code Playgroud)
那么,问题是如何在C#中使用我所获得的RS256算法的公钥来验证这个JWT?如果有一个很好的教程明确描述这个过程,那将是很棒的.但是,如何使用它的一个例子System.IdentityModel.Tokens.Jwt
也可以正常工作.
更新:我明白,我需要做类似下面的代码,但我不知道在哪里获得用于计算SHA256哈希的" 密钥 ".
string tokenStr = "eyJraWQiOiIxZTlnZGs3IiwiYWxnIjoiUlMyNTYifQ.ewogImlzcyI6ICJodHRwOi8vc2VydmVyLmV4YW1wbGUuY29tIiwKICJzdWIiOiAiMjQ4Mjg5NzYxMDAxIiwKICJhdWQiOiAiczZCaGRSa3F0MyIsCiAibm9uY2UiOiAibi0wUzZfV3pBMk1qIiwKICJleHAiOiAxMzExMjgxOTcwLAogImlhdCI6IDEzMTEyODA5NzAsCiAiY19oYXNoIjogIkxEa3RLZG9RYWszUGswY25YeENsdEEiCn0.XW6uhdrkBgcGx6zVIrCiROpWURs-4goO1sKA4m9jhJIImiGg5muPUcNegx6sSv43c5DSn37sxCRrDZZm4ZPBKKgtYASMcE20SDgvYJdJS0cyuFw7Ijp_7WnIjcrl6B5cmoM6ylCvsLMwkoQAxVublMwH10oAxjzD6NEFsu9nipkszWhsPePf_rM4eMpkmCbTzume-fzZIi5VjdWGGEmzTg32h3jiex-r5WTHbj-u5HL7u_KP3rmbdYNzlzd1xWRYTUs4E8nOTgzAUwvwXkIQhOh5TPcSMBYy6X3E7-_gr9Ue6n4ND7hTFhtjYs3cjNKIA08qm5cpVYFMFMG6PkhzLQ";
string[] tokenParts = tokenStr.Split('.');
RSACryptoServiceProvider rsa = new RSACryptoServiceProvider();
rsa.ImportParameters(
new RSAParameters() {
Modulus = FromBase64Url("w7Zdfmece8iaB0kiTY8pCtiBtzbptJmP28nSWwtdjRu0f2GFpajvWE4VhfJAjEsOcwYzay7XGN0b-X84BfC8hmCTOj2b2eHT7NsZegFPKRUQzJ9wW8ipn_aDJWMGDuB1XyqT1E7DYqjUCEOD1b4FLpy_xPn6oV_TYOfQ9fZdbE5HGxJUzekuGcOKqOQ8M7wfYHhHHLxGpQVgL0apWuP2gDDOdTtpuld4D2LK1MZK99s9gaSjRHE8JDb1Z4IGhEcEyzkxswVdPndUWzfvWBBWXWxtSUvQGBRkuy1BHOa4sP6FKjWEeeF7gm7UMs2Nm2QUgNZw6xvEDGaLk4KASdIxRQ"),
Exponent = FromBase64Url("AQAB")
});
HMACSHA256 sha = new HMACSHA256(key);
byte[] hash = sha.ComputeHash(Encoding.UTF8.GetBytes(tokenParts[0] + '.' + tokenParts[1]));
byte[] signature = rsa.Encrypt(hash, …
Run Code Online (Sandbox Code Playgroud) OAuth 2.0定义了客户端请求发送的"状态"参数,以防止跨站点请求攻击.在OpenID规范中提到"nonce"也是如此.除了在ID令牌而不是查询参数中返回"nonce"这一事实之外,它们看起来服务于完全相同的目的.如果有人能解释他们为何分开
多年来,我一直使用OpenID委托登录Stack Overflow(以及其他网站),使用我自己的URI作为OpenID,但让Google处理身份验证.我使用Stack Overflow问题中描述的技术; 所以,我的自定义OpenID http://tupelo-schneck.org/robert解析为包含以下内容的HTML页面:
<link href="https://www.google.com/accounts/o8/ud" rel="openid2.provider" />
<link href="https://www.google.com/profiles/schneck" rel="openid2.local_id" />
Run Code Online (Sandbox Code Playgroud)
然而,现在,我已登录Stack Overflow并让谷歌告诉我" 重要通知: 2015年4月20日,Google帐户的OpenID2将消失.了解详情." 此页面解释了Google已弃用OpenID 2.0,开发人员应将其应用迁移到OpenID Connect.
我是否可以继续使用自定义URI进行OpenID登录,但是委托给Google的OpenID Connect提供商进行身份验证?怎么样?
我已经生成了以下令牌并尝试使用http://jwt.io验证签名. 我还附加了jwks端点的内容,该端点应该包含我需要验证的所有详细信息.
所以我的问题是:我怎样才能在jwt.io网站上说这个签名有效?我错过了证书链参数的一些转换吗?
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6ImEzck1VZ01Gdjl0UGNsTGE2eUYzekFrZnF1RSIsImtpZCI6ImEzck1VZ01Gdjl0UGNsTGE2eUYzekFrZnF1RSJ9.eyJub25jZSI6IjYzNjA3MDM0OTc3NDIzODg2NS5OMlkxTldKbU1EZ3RZbU13TkMwME9XWTNMVGt5TlRJdE9ERXpOell4Wm1NME0yVmxNV1l5TkdOaFlXTXRaVEpqT1MwME4yRmpMVGd6WmpVdFpXWTVOVEEwWmpFMU1qWTEiLCJpYXQiOjE0NzE0MzgxODIsImF0X2hhc2giOiJLWUJpVkl1Uy1YZERzU3NHcWU5dTJBIiwic3ViIjoiMSIsImFtciI6InBhc3N3b3JkIiwiYXV0aF90aW1lIjoxNDcxNDM4MTgyLCJpZHAiOiJpZHNydiIsImlzcyI6Imh0dHBzOi8vZWx3ZWJhcHBsaWNhdGlvbjEuYXp1cmV3ZWJzaXRlcy5uZXQvaWRlbnRpdHkiLCJhdWQiOiJtdmMiLCJleHAiOjE0NzE0Mzg0ODIsIm5iZiI6MTQ3MTQzODE4Mn0.Ehck2-rA09cJzlfURhDMp-WcXm_t_dl-u0Mli3exdv1HxX8i77x5VfFPM6rP4lcpI3lpN8Yj-FefZYDTUY_UmxCYvXf6ILSrhzEfQVaXSPKX1RUQQIDJGPU6NuFLcR416JpUAkE8joYae3WPj5VsM4yNENGGjUANm4qgj6G_mYy_BiXcSqvRGRYwW5GHDsnnANrIw4oktIYS05yCbjdiNYgQZ043L6Pb2p-5eTPCFqG7WRHp208dhg8D3nhtYEov2Kxod93oKHXSp1zf-Ot0cadk6Ss4fClaTE9S1f29lbwxw7ZxI1L3R4oOL3FZPSSHGp4d3a3AdUKOjKvvTVPv6w
{
keys : [{
kty : "RSA",
use : "sig",
kid : "a3rMUgMFv9tPclLa6yF3zAkfquE",
x5t : "a3rMUgMFv9tPclLa6yF3zAkfquE",
e : "AQAB",
n : "qnTksBdxOiOlsmRNd-mMS2M3o1IDpK4uAr0T4_YqO3zYHAGAWTwsq4ms-NWynqY5HaB4EThNxuq2GWC5JKpO1YirOrwS97B5x9LJyHXPsdJcSikEI9BxOkl6WLQ0UzPxHdYTLpR4_O-0ILAlXw8NU4-jB4AP8Sn9YGYJ5w0fLw5YmWioXeWvocz1wHrZdJPxS8XnqHXwMUozVzQj-x6daOv5FmrHU1r9_bbp0a1GLv4BbTtSh4kMyz1hXylho0EvPg5p9YIKStbNAW9eNWvv5R8HN7PPei21AsUqxekK0oW9jnEdHewckToX7x5zULWKwwZIksll0XnVczVgy7fCFw",
x5c : [
"MIIDBTCCAfGgAwIBAgIQNQb+T2ncIrNA6cKvUA1GWTAJBgUrDgMCHQUAMBIxEDAOBgNVBAMTB0RldlJvb3QwHhcNMTAwMTIwMjIwMDAwWhcNMjAwMTIwMjIwMDAwWjAVMRMwEQYDVQQDEwppZHNydjN0ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAqnTksBdxOiOlsmRNd+mMS2M3o1IDpK4uAr0T4/YqO3zYHAGAWTwsq4ms+NWynqY5HaB4EThNxuq2GWC5JKpO1YirOrwS97B5x9LJyHXPsdJcSikEI9BxOkl6WLQ0UzPxHdYTLpR4/O+0ILAlXw8NU4+jB4AP8Sn9YGYJ5w0fLw5YmWioXeWvocz1wHrZdJPxS8XnqHXwMUozVzQj+x6daOv5FmrHU1r9/bbp0a1GLv4BbTtSh4kMyz1hXylho0EvPg5p9YIKStbNAW9eNWvv5R8HN7PPei21AsUqxekK0oW9jnEdHewckToX7x5zULWKwwZIksll0XnVczVgy7fCFwIDAQABo1wwWjATBgNVHSUEDDAKBggrBgEFBQcDATBDBgNVHQEEPDA6gBDSFgDaV+Q2d2191r6A38tBoRQwEjEQMA4GA1UEAxMHRGV2Um9vdIIQLFk7exPNg41NRNaeNu0I9jAJBgUrDgMCHQUAA4IBAQBUnMSZxY5xosMEW6Mz4WEAjNoNv2QvqNmk23RMZGMgr516ROeWS5D3RlTNyU8FkstNCC4maDM3E0Bi4bbzW3AwrpbluqtcyMN3Pivqdxx+zKWKiORJqqLIvN8CT1fVPxxXb/e9GOdaR8eXSmB0PgNUhM4IjgNkwBbvWC9F/lzvwjlQgciR7d4GfXPYsE1vf8tmdQaY8/PtdAkExmbrb9MihdggSoGXlELrPA91Yce+fiRcKY3rQlNWVd4DOoJ/cPXsXwry8pWjNCo5JD8Q+RQ5yZEy7YPoifwemLhTdsBz3hlZr28oCGJ3kbnpW0xGvQb3VHSTVVbeei0CfXoW6iz1"
]
}
]
}
Run Code Online (Sandbox Code Playgroud)
先发帖所以要温柔!:)
我正在为Office 365开发一个MVC .NET 5 Web应用程序,并且正在使用OpenIDConnect框架.我已经设置了OWIN(3)和ADAL(2)以及我的Azure AD应用程序.没有用户操作登录,家庭控制器附加了[Authorize]属性,强制立即登录重定向到Azure AD.我没有在任何Authorize属性中使用角色.
问题:我可以成功登录我的应用程序 - 一次!首次登录后,我关闭浏览器(或在另一台机器上打开一个新浏览器),然后再次点击该应用程序.它将我重定向到我登录的Azure AD登录屏幕,然后它不断在应用程序和Azure之间重定向,直到我得到臭名昭着的400个标题为长期问题.看着饼干商店,我发现它充满了疙瘩.我检查了缓存(Vittorio的EFADALCache配方,虽然我在发现此问题时使用的是TokenCache.DefaultShared)并且它有数百行缓存数据(只有一行成功登录时生成).
我可以看到,当重定向通过输出窗口发生时,每次往返都会生成一个新的访问和刷新令牌:
Microsoft.IdentityModel.Clients.ActiveDirectory Verbose: 1 : 31/07/2015 12:31:52: 15ad306e-e26d-4827-98dc-dea75853788a - AcquireTokenByAuthorizationCodeHandler: Resource value in the token response was used for storing tokens in the cache
iisexpress.exe Information: 0 : 31/07/2015 12:31:52: 15ad306e-e26d-4827-98dc-dea75853788a - AcquireTokenByAuthorizationCodeHandler: Resource value in the token response was used for storing tokens in the cache
Microsoft.IdentityModel.Clients.ActiveDirectory Information: 2 : 31/07/2015 12:31:52: - TokenCache: Deserialized 1 items to token cache.
iisexpress.exe Information: 0 : 31/07/2015 12:31:52: …
Run Code Online (Sandbox Code Playgroud) 我们目前有一个基于OpenID的Google AppEngine应用程序.
我们现在正在尝试将我们的应用程序与我们的客户内部IT系统集成,并且看看,OpenID是一个非常复杂的规范.
我们还看到,Google正朝着OpenID Connect的方向发展(如果您查看Google云端硬盘).
除Google之外还有其他众所周知的公共OpenID Connect提供商吗?
openid-connect ×10
jwt ×3
oauth-2.0 ×3
openid ×3
c# ×2
rsa ×2
asp.net ×1
asp.net-core ×1
asp.net-mvc ×1
azure ×1
jwk ×1
oauth ×1
owin ×1