我是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;
}
}
答案 0 :(得分:0)
根据Ming的建议审查了Thinktecture日志,我发现问题是框架正在调用IsUserActiveAsync,并且由于我的模拟代码中的一个小错误而返回false。当我解决这个问题时,一切都开始了。