无法设置 OWIN + OneLogin + Bearer
Posted
技术标签:
【中文标题】无法设置 OWIN + OneLogin + Bearer【英文标题】:Can't setup OWIN + OneLogin + Bearer 【发布时间】:2018-06-14 12:05:27 【问题描述】:我正在尝试使用授权令牌来保护我的 WebAPI 项目。我不想使用 cookie,我只想使用 Authorization
这样的标头:Authorization: Bearer xxx_access_or_id_token_xxx
。我使用OneLogin OIDC 作为外部提供者。这是我的Startup.cs
using Microsoft.Owin;
using Microsoft.Owin.Security;
using Microsoft.Owin.Security.DataHandler.Encoder;
using Microsoft.Owin.Security.Jwt;
using Owin;
using System.Web.Http;
public void Configuration(IAppBuilder app)
var issuer = "https://openid-connect.onelogin.com/oidc/";
var audience = ConfigurationManager.AppSettings["OneLoginClientId"];
var secret = TextEncodings.Base64.Encode((TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["OneLoginClientSecret"])));
app.UseJwtBearerAuthentication(new JwtBearerAuthenticationOptions
AuthenticationMode = AuthenticationMode.Active,
AllowedAudiences = new[] audience ,
IssuerSecurityTokenProviders = new[] new SymmetricKeyIssuerSecurityTokenProvider(issuer, secret)
);
HttpConfiguration httpConfig = new HttpConfiguration();
WebApiConfig.Register(httpConfig);
app.UseWebApi(httpConfig);
我也有控制器:
public class ValueController: ApiController
[HttpGet]
[AllowAnonymous]
public string NotSecure()
return "Not secure";
[HttpGet]
[Authorize]
public strnig Secure()
return "Secure";
好的,现在让我们来看看 OneLogin 部分。
经过身份验证流程后,我得到了 5 个字段:access_token
、expires_in
、id_token
,即 JWT、refresh_token
和 token_type
。
使用jwt.io 我可以解析我的id_token
,我有这样的东西:
标题:
"alg": "RS256",
"typ": "JWT",
"kid": "xxx"
有效载荷:
"sub": "33827172",
"email": "john.smith@company.com",
"name": "John Smith",
"iat": 1515083928,
"exp": 1515091128,
"aud": "onelogin_client_id",
"iss": "https://openid-connect.onelogin.com/oidc"
我正在尝试使用授权令牌发送到我的 api 请求。我尝试同时发送:access_token
和 id_token
,但每次我调用安全操作时,都会收到 401。
我该如何解决这个问题?
也许我错过了什么?
Nuget:
Microsoft.Owin -v 3.1.0
Microsoft.Owin.* -v 3.1.0
System.IdentityModel.Tokens.Jwt
-v 4.0.1
【问题讨论】:
你安装Microsoft.Owin.Host.SystemWeb
了吗?
您是否检查过只在授权标头中放置 access_token 而没有放置“承载”字样?
@talha-junaid,是的,当然。它是与另一个软件包一起安装的。
需要调试 SymmetricKeyIssuerSecurityTokenProvider
【参考方案1】:
好的,问题出在签名上。 以下是我的工作方式:
public static class AuthConfig
public static JwtBearerAuthenticationOptions GetOptions()
var keyResolver = new KeyResolver(System.Configuration.ConfigurationManager.AppSettings["OneLoginOpenIdConfigurationDomain"]); //https://<your_domain>.onelogin.com/oidc
return new JwtBearerAuthenticationOptions
AuthenticationMode = AuthenticationMode.Active,
TokenValidationParameters = new TokenValidationParameters
ValidIssuer = System.Configuration.ConfigurationManager.AppSettings["OneLoginJWTIssuer"], //https://openid-connect.onelogin.com/oidc
ValidAudience = System.Configuration.ConfigurationManager.AppSettings["OneLoginClientId"],
IssuerSigningKeyResolver = (token, securityToken, identifier, paramaters) => keyResolver.GetSigningKey(identifier)
;
#region Helpers
public class KeyResolver
private readonly OpenIdConnectConfiguration openIdConfig;
private static readonly TaskFactory TaskFactory = new TaskFactory(CancellationToken.None, TaskCreationOptions.None, TaskContinuationOptions.None, TaskScheduler.Default);
public KeyResolver(string domain)
var cm = new ConfigurationManager<OpenIdConnectConfiguration>($"domain/.well-known/openid-configuration");
openIdConfig = TaskFactory.StartNew(async () => await cm.GetConfigurationAsync()).Unwrap().GetAwaiter().GetResult();
public SecurityKey GetSigningKey(SecurityKeyIdentifier identifier)
// Find the security token which matches the identifier
var securityToken = openIdConfig.SigningTokens.FirstOrDefault(t =>
// Each identifier has multiple clauses. Try and match for each
foreach (var securityKeyIdentifierClause in identifier)
if (t.MatchesKeyIdentifierClause(securityKeyIdentifierClause))
return true;
return false;
);
// Return the first key of the security token (if found)
return securityToken?.SecurityKeys.FirstOrDefault();
#endregion
这里是Startup.cs
:
public class Startup
public void Configuration(IAppBuilder app)
HttpConfiguration httpConfig = new HttpConfiguration();
WebApiConfig.Register(httpConfig);
app.UseJwtBearerAuthentication(AuthConfig.GetOptions());
app.UseWebApi(httpConfig);
我也将此添加到 WebApiConfig
,但我不确定这是否真的有帮助。
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter("Bearer"));
Nuget:
<package id="Microsoft.AspNet.Cors" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.Identity.Core" version="2.2.1" targetFramework="net45" />
<package id="Microsoft.AspNet.Identity.EntityFramework" version="2.2.1" targetFramework="net45" />
<package id="Microsoft.AspNet.Identity.Owin" version="2.2.1" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Owin" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.IdentityModel.Logging" version="1.1.5" targetFramework="net45" />
<package id="Microsoft.IdentityModel.Protocol.Extensions" version="1.0.4.403061554" targetFramework="net45" />
<package id="Microsoft.IdentityModel.Tokens" version="5.1.5" targetFramework="net45" />
<package id="Microsoft.Owin" version="3.1.0" targetFramework="net45" />
<package id="Microsoft.Owin.Host.SystemWeb" version="3.1.0" targetFramework="net45" />
<package id="Microsoft.Owin.Security" version="3.1.0" targetFramework="net45" />
<package id="Microsoft.Owin.Security.Cookies" version="3.1.0" targetFramework="net45" />
<package id="Microsoft.Owin.Security.Jwt" version="3.1.0" targetFramework="net45" />
<package id="Microsoft.Owin.Security.OAuth" version="3.1.0" targetFramework="net45" />
<package id="Microsoft.Owin.Security.OpenIdConnect" version="3.1.0" targetFramework="net45" />
<package id="Owin" version="1.0" targetFramework="net45" />
<package id="System.IdentityModel.Tokens.Jwt" version="4.0.4.403061554" targetFramework="net45" />
在我的测试中,大于 4.0.4 的版本 System.IdentityModel.Tokens.Jwt
无法正常工作,所以就这样吧。
我还要感谢Auth0 和他们的Github 提供的出色手册。
【讨论】:
以上是关于无法设置 OWIN + OneLogin + Bearer的主要内容,如果未能解决你的问题,请参考以下文章
无法让 OpenID 身份验证与 Onelogin 和 Azure Web 应用程序一起使用
使用 OneLogin 和 DotNetOpenAuth 在 CrossDomain 上进行 ASP.Net 单点登录