IdentityServer3 - UserInfo端点获取无效令牌

时间:2015-07-22 19:38:40

标签: identityserver3

我是IdentityServer3的新手,我刚刚开始设置它。它似乎进展顺利,我一直在研究混合流程的MVC应用程序类似于Kevin Dockx的Pluralsight课程(http://www.pluralsight.com/courses/building-securing-restful-api-aspdotnet)--我使用自定义用户服务。

从MVC应用程序到我的身份服务器的身份验证效果很好,但是当我调用userinfo端点时,我总是得到一个未授权的,响应中的Bearer是"无效的令牌"。

我传入了从原始OpenIdConnectAuthentication调用返回的访问令牌,并在JWT调试器中解码为以下内容:

{
  "client_id": "mvc",
  "scope": [
    "openid",
    "profile",
    "actioncenter"
  ],
 "sub": "erik",
 "amr": "password",
 "auth_time": 1437591012,
 "idp": "idsrv",
 "iss": "https://id.local/",
 "aud": "https://id.local/resources",
 "exp": 1437594614,
 "nbf": 1437591014
}

我还注意到,响应内容返回的内容类似于" RunToCompletion"。我已经从Github下载了源代码,看看调试的可能性,并怀疑它比我运行的NuGet包(1.6.2)更新。

我怀疑我做错了什么,但我还没能看到它。任何帮助将不胜感激。

我已经包含了我认为相关的代码。

来自ID Server:

static class Clients
{
    public static List<Client> Get()
    {
        return new List<Client>
        {                
            new Client
            {
                ClientName = "MVC Client",
                ClientId = "mvc",
                Enabled = true,
                RequireConsent = true,

                RedirectUris = new List<string>     
                                   { "https://localhost:44300/" },
                AccessTokenType = AccessTokenType.Jwt,

                Flow = Flows.Hybrid,
                ScopeRestrictions = new List<string>()
                {
                    Constants.StandardScopes.OpenId,
                    Constants.StandardScopes.Profile,                       
                    "actioncenter"
                }

            }
        };
    }
static class Scopes
{
    public static List<Scope> Get()
    {
        return new List<Scope>
        {
            //identity scopes
            StandardScopes.OpenId,
            StandardScopes.Profile,
            //StandardScopes.EmailAlwaysInclude,
            //StandardScopes.PhoneAlwaysInclude,
            StandardScopes.Roles,

            //resource scopes
            new Scope
            {
                Name = "actioncenter",
                Type = ScopeType.Resource,
                Emphasize = false,
                Enabled = true,
                DisplayName = "Action Center"                    
            }
        };
    }
public class NwpIdentityUserService : IUserService
{
    public class CustomUser
    {
        public string Subject { get; set; }  // identifier for user
        public string Provider { get; set; } // provider name that did the auth for the user
        public string ProviderId { get; set; } // userid from the provider for this user
        public List<Claim> Claims { get; set; }
    }

    public Task<AuthenticateResult> PreAuthenticateAsync(SignInMessage message)
    {
        return Task.FromResult<AuthenticateResult>(null);
    }

    public Task<AuthenticateResult> AuthenticateLocalAsync(string username, string password, SignInMessage message)
    {
        AuthenticateResult result;

        if (username != password)
            result = new AuthenticateResult("Invalid username/password");
        else
            result = new AuthenticateResult(username, "erik", new List<Claim> { new Claim("role", "writer") });

        return Task.FromResult(result);
    }

    public Task<AuthenticateResult> AuthenticateExternalAsync(ExternalIdentity externalUser, SignInMessage message)
    {
        //var ourUserId = GetOurUserId()
        // LOGIC:
        // From the information in externalUser, determine our user ID
        // Assuming valid, return a new authenticate result with the nwp user name, claims, etc.

        return Task.FromResult<AuthenticateResult>(null);
    }

    public Task SignOutAsync(ClaimsPrincipal subject)
    {
        return Task.FromResult(0);
    }

    public Task<IEnumerable<Claim>> GetProfileDataAsync(ClaimsPrincipal subject, IEnumerable<string> requestedClaimTypes = null)
    {
        var nwpUserId = GetOurUserId(subject);
        if (nwpUserId == null)
            return Task.FromResult<IEnumerable<Claim>>(null);

        var claims = GetOurClaimsForUser(nwpUserId);
        return Task.FromResult(claims.Where(a => requestedClaimTypes.Contains(a.Type)));
    }

    private List<Claim> GetOurClaimsForUser(int? ourUserId)
    {
        var claims = new List<Claim>();
        claims.Add(new Claim("role", "basicuser"));

        return claims;
    }

    public Task<bool> IsActiveAsync(ClaimsPrincipal subject)
    {
        return Task.FromResult(GetOurUserId(subject) != null);
    }

    private int? GetOurUserId(ClaimsPrincipal subject)
    {
        var userclaim = subject.Claims.FirstOrDefault(a => a.Type == "name");
        if (userclaim == null)
            return null;

        return 123;
    }
}

以下是来自MVC客户端应用程序的相关代码 - response.StatusCode始终未经授权使用&#34;无效令牌&#34;下面的承载消息:

public class Startup
{
    public void Configuration(IAppBuilder app)
    {
        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = "Cookies"
        });

        app.UseOpenIdConnectAuthentication(new OpenIdConnectAuthenticationOptions
        {
            ClientId = "mvc",
            Authority = "https://id.local/identity/",
            RedirectUri = "https://localhost:44300/",
            SignInAsAuthenticationType = "Cookies",
            ResponseType = "code id_token token",
            Scope = "openid profile actioncenter",

            Notifications = new OpenIdConnectAuthenticationNotifications()
            {
                MessageReceived = async n =>
                {
                    var userInfo = await GetUserInfoFromEndpoint(n.ProtocolMessage.AccessToken);
                }

            }
        });
    }

    private async Task<JObject> GetUserInfoFromEndpoint(string accessToken)
    {
        var client = new HttpClient();
        client.SetBearerToken(accessToken);

        var response = await client.GetAsync("https://id.local/identity/connect/userinfo");

        if (response.StatusCode == HttpStatusCode.OK)
        {
            var json = await response.Content.ReadAsStringAsync();
            return JObject.Parse(json);
        }
        var result = response.Content.ReadAsStringAsync();
        return null;
    }

}

1 个答案:

答案 0 :(得分:0)

根据Ming的建议审查了Thinktecture日志,我发现问题是框架正在调用IsUserActiveAsync,并且由于我的模拟代码中的一个小错误而返回false。当我解决这个问题时,一切都开始了。