- ABP Framework version: v4.4.3
- UI type: Angular
- DB provider: EF Core
- Tiered Identity Server Separated (Angular): yes
- Exception message and stack trace:
InvalidOperationException: SignInAsync when principal.Identity.IsAuthenticated is false is not allowed when AuthenticationOptions.RequireAuthenticatedSignIn is true. Microsoft.AspNetCore.Authentication.AuthenticationService.SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties) IdentityServer4.Hosting.IdentityServerAuthenticationService.SignInAsync(HttpContext context, string scheme, ClaimsPrincipal principal, AuthenticationProperties properties) Siemens.LDA.CleanOrder.Controllers.AuthenticationController.ExternalLoginBackAsync() in AuthenticationController.cs await HttpContext.SignInAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme, lambda_method1783(Closure , object ) Microsoft.AspNetCore.Mvc.Infrastructure.ActionMethodExecutor+TaskOfActionResultExecutor.Execute(IActionResultTypeMapper mapper, ObjectMethodExecutor executor, object controller, object[] arguments) System.Threading.Tasks.ValueTask<TResult>.get_Result()
Steps to reproduce the issue:"
- ConfigureAuthentication
context.Services.AddAuthentication(options=> { //options.RequireAuthenticatedSignIn = false; }) .AddJwtBearer(options => { options.Authority = configuration["AuthServer:Authority"]; options.RequireHttpsMetadata = Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]); options.Audience = "CleanOrder"; options.BackchannelHttpHandler = new HttpClientHandler { ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator }; }) //.AddCookie("CleanOrder.MyId") .AddOpenIdConnect("MyId", "OpenID Connect", options => { options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; options.SignOutScheme = IdentityServerConstants.SignoutScheme; options.Authority = "https://myid.siemens.com/"; options.CallbackPath = "/"; options.ClientSecret = configuration["MyIdAuthServer:ClientSecret"]; options.ClientId = configuration["MyIdAuthServer:ClientId"]; options.ResponseType = OpenIdConnectResponseType.Code; options.SaveTokens = true; //options.SignedOutRedirectUri = "http://localhost:4300"; options.BackchannelHttpHandler = new HttpClientHandler { ServerCertificateCustomValidationCallback = HttpClientHandler.DangerousAcceptAnyServerCertificateValidator };
- Environment (Angular)
oAuthConfig: { issuer: 'https://myid.siemens.com', redirectUri: 'https://localhost:44361/authentication/token', clientId: 'ClienID', responseType: 'code', scope: 'openid profile email', }
- Controller
[HttpGet("token")] public ActionResult AuthAsync() { Console.WriteLine("===========token=================="); var callbackUrl = Url.Action("ExternalLoginback"); var properties = new AuthenticationProperties() { // actual redirect endpoint for your app RedirectUri = callbackUrl, AllowRefresh = true, }; return Challenge(properties, "MyId"); } [HttpGet("signin-oidc")] public async Task<RedirectResult> ExternalLoginBackAsync() { Console.WriteLine("===========callback=================="); // read external identity from the temporary cookie var result = await HttpContext.AuthenticateAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); if (result?.Succeeded != true) { throw new Exception("External authentication error"); } // retrieve claims of the external user var externalUser = result.Principal; if (externalUser == null) { throw new Exception("External authentication error"); } // retrieve claims of the external user var claims = externalUser.Claims.ToList(); // try to determine the unique id of the external user - the most common claim type for that are the sub claim and the NameIdentifier // depending on the external provider, some other claim type might be used var userIdClaim = claims.FirstOrDefault(x => x.Type == JwtClaimTypes.Subject); if (userIdClaim == null) { userIdClaim = claims.FirstOrDefault(x => x.Type == ClaimTypes.NameIdentifier); } if (userIdClaim == null) { throw new Exception("Unknown userid"); } var externalUserId = userIdClaim.Value; var externalProvider = userIdClaim.Issuer; // get userInfo var user = await _appUserService.GetByUserNameAsync(externalUserId.Split('|')[1]); var clientUrl = _configuration["App:ClientUrl"]; if (user != null) { // issue authentication cookie for user await HttpContext.SignInAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme, new ClaimsPrincipal( new ClaimsIdentity( new List<Claim> { new Claim(AbpClaimTypes.UserId,user.Id.ToString()), new Claim(AbpClaimTypes.UserName,user.UserName), new Claim(AbpClaimTypes.Email,user.Email) } ) ) ); //delete temporary cookie used during external authentication //await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme); } else { clientUrl += "/userNotExsit"; } return Redirect(clientUrl); }
It is the first time to integrate third-party authentication system. I have limited knowledge of authentication and experience with JWT Access Token. I need help.
- My Reference
11 Answer(s)
-
0
Hi,
Can you try testing external login with IdentityServer and check the logs?
-
0
你好。我已经完成了第三方认证部分,获得了所需的用户信息,并且在数据库中查到了该用户,现在需要做的是登录并且返回到客户端站点,但我遇到了一个如上所示的异常信息,如果我将 ConfigureAuthentication 中的 RequireAuthenticatedSignIn 设置为 false 后,该问题即不存在,会跳转到客户端,但是并没有登录成功。希望能得到您的帮助。谢谢!
-
0
Hi,
Can you share a project to reproduce? shiwei.liang@volosoft.com thanks.
-
0
很抱歉,因为第三方的认证需要内网才可以进行,这意味着您无法进行认证的调试,所以您是否还需要项目?
-
0
Hi,
You can try to integration external login without ABP application, if what works you can share the project with us, we can help you implement it in the ABP application.
-
0
Hi, 我已经卡在这个问题上一天了,经过修改已经可以实现不设置
RequireAuthenticatedSignIn = false
使用HttpContext.SingIn
不会报错,代码改动如下:var isUser = new IdentityServerUser(user.Id.ToString()); var principal = isUser.CreatePrincipal(); principal.AddIdentity( new ClaimsIdentity( new List<Claim> { new Claim(AbpClaimTypes.UserId,user.Id.ToString()), new Claim(AbpClaimTypes.UserName,user.UserName), new Claim(AbpClaimTypes.Email,user.Email) } ) ); await HttpContext.SignInAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme, principal);
但在跳转回 Angular 时,https://localhost:44361/api/abp/application-configuration 接口返回的仍然是没有登录,返回结果如下图所示:
所以我的问题的关键在于如何使当前用户登录上去,这块我理解的不到位,是否是根据 cookie 或者 access token 来实现校验的?api/abp/application-configuration 接口的源代码链接方便发我一下么。 另外想问下是否提供远程协助。
PS:不使用 Abp 框架中的 angular 部分, 采用 asp.net 来测试是否可以跑通,我认为意义不是很大。
随时期待您的回复。
-
0
You can use Github as an external login to check the entire process.
Create a new project with angular as UI then add
AddGitHub
https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers
-
0
好的。我将会试试使用
GitHub
认证,跑下整个流程。 -
0
ok
-
0
已经在开发环境解决了认证授权问题,但是在部署到生产环境时,在请求第三方认证站点时出现了CORS 问题,部署环境为 IIS,请问如何解决这个问题。 尝试过以下两种方案: 第一种,使用 Angular Proxy config,但是没生效 第二种,将
oAuthConfig
的issuer
设置为源站,在 IIS 中将请求转发到认证站点,但出现了新问题main-es2015.22bb79fb162f00377e5b.js:1 invalid issuer in discovery document expected: https://源站.com.cn current: https://认证.xxx.com
,所以还是需要使用第一种,直接解决跨域的问题 -
0
Please create a new question(English).