【发布时间】:2020-10-28 15:27:35
【问题描述】:
我正在使用 IdentityServer4 并尝试手动验证我的 Asp.Net Core 3.1 客户端(手动创建请求以了解流程)。 这是我的客户登录信息:
[HttpGet]
public IActionResult ManualLogin()
{
var myNonce = Guid.NewGuid().ToString();
var myState = Guid.NewGuid().ToString();
var req = "https://localhost:5000/connect/authorize?" +
"client_id=mvc" +
"&redirect_uri=https://localhost:44381/signin-oidc" +
"&response_type=code id_token" +
"&scope=openid profile offline_access email" +
"&response_mode=form_post" +
$"&nonce={myNonce}" +
$"&state={myState}";
return Redirect(req);
}
这个登录方法工作正常,一切正常,但我不想使用它:
//[HttpGet]
//public async Task LoginAsync()
//{
// await HttpContext.ChallengeAsync(OpenIdConnectDefaults.AuthenticationScheme, new AuthenticationProperties
// {
// RedirectUri = "https://localhost:44381/Home/external-login-callback"
// });
// }
我客户的 startup.cs:
public void ConfigureServices(IServiceCollection services)
{
// for using IHttpClientFactory
services.AddHttpClient();
JwtSecurityTokenHandler.DefaultInboundClaimTypeMap.Clear();
// adding Authentication services to DependencyInjection
services.AddAuthentication(config =>
{
config.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
config.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme)
.AddOpenIdConnect(OpenIdConnectDefaults.AuthenticationScheme, config =>
{
config.SignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
config.Authority = "https://localhost:5000";
config.ClientId = "mvc";
config.ClientSecret = "secret";
config.SaveTokens = true;
config.UseTokenLifetime = false;
// Hybrid Flow
config.ResponseType = "code id_token";
config.Scope.Add("openid");
config.Scope.Add("offline_access");
config.Scope.Add("profile");
config.Scope.Add("email");
config.GetClaimsFromUserInfoEndpoint = true;
config.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = JwtClaimTypes.GivenName,
RoleClaimType = JwtClaimTypes.Role,
};
// config.AuthenticationMethod = OpenIdConnectRedirectBehavior.FormPost;
});
services.AddControllersWithViews();
}
我的客户的定义:
new Client
{
ClientId = "mvc",
ClientName ="My mvc client testing",
ClientSecrets = { new Secret("secret".Sha256()) },
AllowedGrantTypes = GrantTypes.Hybrid,
// where to redirect to after login
RedirectUris = { "https://localhost:44381/signin-oidc" },
// where to redirect to after logout
PostLogoutRedirectUris = { "https://localhost:44381/signout-callback-oidc" },
AllowedScopes = new List<string>
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile,
},
AllowOfflineAccess = true,
UpdateAccessTokenClaimsOnRefresh = true,
AccessTokenType = AccessTokenType.Reference,
RequireConsent = false,
RequireClientSecret = true,
//AlwaysIncludeUserClaimsInIdToken = true,
RequirePkce = false,
}
我的 IS4 的 startup.cs:
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
var builder = services.AddIdentityServer()
.AddInMemoryIdentityResources(Config.IdentityResources)
.AddInMemoryApiScopes(Config.ApiScopes)
.AddInMemoryClients(Config.Clients)
.AddTestUsers(TestUsers.Users);
builder.AddDeveloperSigningCredential();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseStaticFiles();
app.UseRouting();
app.UseIdentityServer();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
});
}
}
客户端成功重定向到IS4登录页面,然后我可以对用户进行身份验证,并且在我的客户端上重定向回signin-oidc url时,我得到了500 Internal Server Error:
Unable to unprotect the message.State.
Exception: Unable to unprotect the message.State.
Unknown location
Exception: An error was encountered while handling the remote login.
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler<TOptions>.HandleRequestAsync()
Exception: An error was encountered while handling the remote login.
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler<TOptions>.HandleRequestAsync()
Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
我没有多个 oidc,只有一个!我错过了什么?
更新1:@ToreNestenius 评论后:
我把请求的redirect_uri改成了:
&redirect_uri=https://localhost:44381/home/MyCallback"
并将回调添加到 IS4 客户端的配置中,然后这是我的回调:
[HttpPost]
[ActionName("mycallback")]
public async Task mycallbackAsync(
string code,
string scope,
string state,
string session_state,
string login_required)
{
var theRequest = $"https://localhost:5000/connect/token";
var client = _httpClientFactory.CreateClient();
var theContent = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string,string>("client_id","mvc"),
new KeyValuePair<string,string>("client_secret","secret"),
new KeyValuePair<string,string>("grant_type","hybrid"),
new KeyValuePair<string,string>("code",code),
new KeyValuePair<string,string>("redirect_uri", "https://localhost:5002/home/mycallback"),
});
theContent.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
var base64StringUserPass = Convert.ToBase64String(Encoding.ASCII.GetBytes($"mvc:secret"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", base64StringUserPass);
var response = await client.PostAsync(req, theContent);
if (!response.IsSuccessStatusCode)
{
Console.WriteLine(response.StatusCode);
return;
}
var content = await response.Content.ReadAsStringAsync();
var theAccessToken = JsonConvert.DeserializeObject<Token>(content);
// -----------------------------
// get user info
//var access_token = theAccessToken.access_token;
//string userInfo = await getUserInfoAsync(access_token);
}
现在我可以正确处理回调,然后发出 accessToken 并获取 userInfo。
【问题讨论】:
标签: asp.net-core oauth-2.0 identityserver4 openid-connect