Exemplo n.º 1
0
        public async Task <IActionResult> Callback(string returnUrl)
        {
            if (string.IsNullOrEmpty(returnUrl))
            {
                returnUrl = "~/";
            }
            ;
            // Validate returnUrl - either it is a valid OIDC URL or back to a local page.
            if (Url.IsLocalUrl(returnUrl) == false && _interaction.IsValidReturnUrl(returnUrl) == false)
            {
                // User might have clicked on a malicious link - should be logged.
                throw new Exception("Invalid return URL.");
            }
            // Read external identity from the temporary cookie.
            // At this point registered claims transformation will run (the ClaimsTransformer class).
            // This is triggered when HttpContext.AuthenticateAsync method is called (which is done inside GetExternalLoginInfoAsync method of SignInManager).
            var externalLoginInfo = await _signInManager.GetExternalLoginInfoAsync();

            if (externalLoginInfo == null)
            {
                throw new Exception($"Cannot read external login information from {externalLoginInfo.LoginProvider}.");
            }
            var user = await _userManager.FindByLoginAsync(externalLoginInfo.LoginProvider, externalLoginInfo.ProviderKey);

            // If user with the specified login is null, this means that we have to do with a brand new user.
            if (user == null)
            {
                // Retrieve claims of the external user.
                var claims = externalLoginInfo.Principal.Claims.ToList();
                // We can choose to auto-provision the user or initiate a custom workflow for user registration.
                user = await AutoProvisionExternalUserAsync(Guid.NewGuid().ToString(), claims);

                // Save user external login.
                await _userManager.AddLoginAsync(user, externalLoginInfo);
            }
            await _events.RaiseAsync(new UserLoginSuccessEvent(externalLoginInfo.LoginProvider, externalLoginInfo.Principal.GetSubjectId(), user.Id, user.UserName));

            // Save user tokes retrieved from external provider.
            await _signInManager.UpdateExternalAuthenticationTokensAsync(externalLoginInfo);

            await _signInManager.ExternalLoginSignInAsync(externalLoginInfo.LoginProvider, externalLoginInfo.ProviderKey, isPersistent : true);

            // Check if external login is in the context of an OIDC request.
            var context = await _interaction.GetAuthorizationContextAsync(returnUrl);

            if (context != null && await _clientStore.IsPkceClientAsync(context.ClientId))
            {
                // If the client is PKCE then we assume it's native, so this change in how to return the response is for better UX for the end user.
                return(View("Redirect", new RedirectViewModel {
                    RedirectUrl = returnUrl
                }));
            }
            return(Redirect(returnUrl));
        }