app.UseIdentityServerBearerTokenAuthentication和UserInfo

时间:2016-10-25 01:51:44

标签: oauth oauth-2.0 identityserver3 openid-connect

对于我的WebAPI,我正在使用:     public void ConfigureAuth(IAppBuilder app)     {

app.UseIdentityServerBearerTokenAuthentication( new IdentityServerBearerTokenAuthenticationOptions
{
    Authority = ConfigurationManager.AppSettings[ "ida:Authority" ],
    RequiredScopes = new[ ]
    {
        "XXXXAPI"
    }
} );

}

我的身份验证没问题,但我需要获取UserInfo端点提供的角色和其他信息。

UseIdentityServerBearerTokenAuthentication是自动执行此操作还是存在OpenIdConnectAuthenticationNotifications.AuthroizationCodeReceived等事件,我应该使用它来设置ClaimsIdentity?

2 个答案:

答案 0 :(得分:0)

您必须使用OAuth2 + JWT和一些自定义配置来保存访问令牌中的用户角色和其他声明。

  1. 在Web.config中添加这些值

    <appSettings>
       <add key="as:AudienceId" value="414e1927a3884f68abc79f7283837fd1" />
       <add key="as:AudienceSecret" value="qMCdFDQuF23RV1Y-1Gq9L3cF3VmuFwVbam4fMTdAfpo" />
    </appSettings>
    
  2. 编写CustomJwtFormat类

    using Microsoft.Owin.Security;
    using Microsoft.Owin.Security.DataHandler.Encoder;
    using System;
    using System.Configuration;
    using System.IdentityModel.Tokens;
    using Thinktecture.IdentityModel.Tokens;
    public class CustomJwtFormat : ISecureDataFormat<AuthenticationTicket>
    {
    
    private readonly string _issuer = string.Empty;
    
    public CustomJwtFormat(string issuer)
    {
        _issuer = issuer;
    }
    
    public string Protect(AuthenticationTicket data)
    {
        if (data == null)
        {
            throw new ArgumentNullException("data");
        }
    
        string audienceId = ConfigurationManager.AppSettings["as:AudienceId"];
    
        string symmetricKeyAsBase64 = ConfigurationManager.AppSettings["as:AudienceSecret"];
    
        var keyByteArray = TextEncodings.Base64Url.Decode(symmetricKeyAsBase64);
    
        var signingKey = new HmacSigningCredentials(keyByteArray);
    
        var issued = data.Properties.IssuedUtc;
    
        var expires = data.Properties.ExpiresUtc;
    
        var token = new JwtSecurityToken(_issuer, audienceId, data.Identity.Claims, issued.Value.UtcDateTime, expires.Value.UtcDateTime, signingKey);
    
        var handler = new JwtSecurityTokenHandler();
    
        var jwt = handler.WriteToken(token);
    
        return jwt;
    }
    }
    
  3. 创建自定义authenticationProvider

    using System.Collections.Generic;
    using System.Linq;
    using System.Security.Claims;
    using System.Threading.Tasks;
    using Microsoft.Owin.Security;
    using Microsoft.Owin.Security.OAuth;
    public class ApplicationOAuthProvider : OAuthAuthorizationServerProvider
    {
    public override Task ValidateClientAuthentication(OAuthValidateClientAuthenticationContext context)
    {
        context.Validated();
        return Task.FromResult<object>(null);
    }
    public override async Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
    {
        context.OwinContext.Response.Headers.Add("Access-Control-Allow-Origin", new[] { "*" });
    
        using (AuthRepository _repo = new AuthRepository())
        {
            User user = await _repo.FindUser(context.UserName, context.Password);
    
            if (user == null)
            {
                context.SetError("invalid_grant", "The user name or password is incorrect.");
                return;
            }
        }
    
        var identity = new ClaimsIdentity(context.Options.AuthenticationType);
        identity.AddClaim(new Claim("unique_name", context.UserName));
        identity.AddClaim(new Claim("role", "user"));
    
        context.Validated(identity);
    }
    }
    
  4. 配置自定义设置

        private static void ConfigureOAuthTokenGeneration(IAppBuilder app)
    {
    
        OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
        {
            //For Dev enviroment only (on production should be AllowInsecureHttp = false)
            AllowInsecureHttp = true,
            TokenEndpointPath = new PathString("/oauth/token"),
            AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
            Provider = new ApplicationOAuthProvider(),
            AccessTokenFormat = new CustomJwtFormat("http://localhost/")
        };
    
        // OAuth 2.0 Bearer Access Token Generation
        app.UseOAuthAuthorizationServer(OAuthServerOptions);
    }
    private static void ConfigureOAuthTokenConsumption(IAppBuilder app)
    {
    
        var issuer = "http://localhost/";
        string audienceId = ConfigurationManager.AppSettings["as:AudienceId"];
        byte[] audienceSecret = TextEncodings.Base64Url.Decode(ConfigurationManager.AppSettings["as:AudienceSecret"]);
    
        // Api controllers with an [Authorize] attribute will be validated with JWT
        app.UseJwtBearerAuthentication(
            new JwtBearerAuthenticationOptions
            {
                AuthenticationMode = AuthenticationMode.Active,
                AllowedAudiences = new[] { audienceId },
                IssuerSecurityTokenProviders = new IIssuerSecurityTokenProvider[]
                {
                    new SymmetricKeyIssuerSecurityTokenProvider(issuer, audienceSecret)
                }
            });
    }
    public void Configuration(IAppBuilder app(
    {
                app.UseAutofacMvc();
        ConfigureOAuthTokenGeneration(app);
        ConfigureOAuthTokenConsumption(app);
        //other codes
    }
    
  5. 如果您想从访问令牌获取userInfo,请按以下步骤操作:

        public static string GetUserNameFromOAuth(HttpRequestMessage Request)
        {
        if (Request.Headers.Contains("Authorization"))
        {
            var authHeader = Request.Headers.GetValues("Authorization");
            var authEncoded = authHeader.FirstOrDefault();
            var authList = authEncoded.Split(' ');
            var payload = authList[1];
    
            var symmetricKeyAsBase64 = ConfigurationManager.AppSettings["as:AudienceSecret"];
            var keyByteArray = TextEncodings.Base64Url.Decode(symmetricKeyAsBase64);
    
            var signingKey = new HmacSigningCredentials(keyByteArray);
            string token = JWT.JsonWebToken.Decode(payload, keyByteArray);
            var jsonObject = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(token);
            var userName = jsonObject.FirstOrDefault(p => p.Key == "unique_name").Value;
            return userName;
        }
        return "";
        }
    
  6. 邮递员测试:

  7. enter image description here

答案 1 :(得分:0)

app.UseIdentityServerBearerTokenAuthentication会自动设置角色和范围。

出于某些未知原因,我只在调用者是UserInfoEndpoint时才从UserService的GetProfileDataAsync返回数据。一旦我摆脱了这段代码,就会自动填充所有角色。