private async Task <Entities.User> AutoProvisionWindowsUser(string provider,
                                                                    string providerUserId, IEnumerable <Claim> claims)
        {
            if (_windowsKeyMap.ContainsKey(providerUserId))
            {
                // find matching user
                var existingUser = await
                                   _localUserService.GetUserBySubjectAsync(_windowsKeyMap[providerUserId]);

                if (existingUser != null)
                {
                    await _localUserService.AddExternalProviderToUser(
                        existingUser.Subject,
                        provider,
                        providerUserId);

                    await _localUserService.SaveChangesAsync();

                    return(existingUser);
                }
            }

            var user = _localUserService.ProvisionUserFromExternalIdentity(provider, providerUserId,
                                                                           new List <Claim>());
            await _localUserService.SaveChangesAsync();

            return(user);
        }
        public async Task <IActionResult> RegisterForMfa(string returnUrl)
        {
            var secret = string.Empty;

            using (var rng = new RNGCryptoServiceProvider())
            {
                byte[] tokenData = new byte[64];
                rng.GetBytes(tokenData);

                var result = new StringBuilder(16);
                for (int i = 0; i < 16; i++)
                {
                    var rnd = BitConverter.ToUInt32(tokenData, i * 4);
                    var idx = rnd % chars.Length;

                    result.Append(chars[idx]);
                }

                secret = result.ToString();
            }

            // read identity from the temporary cookie
            var resultIdent = await HttpContext.AuthenticateAsync("idsrv.mfa");

            if (resultIdent?.Succeeded != true)
            {
                throw new Exception("MFA authentication error");
            }
            var subject = resultIdent.Principal.FindFirst(JwtClaimTypes.Subject)?.Value;

            var user = await _localUserService.GetUserBySubjectAsync(subject);

            var keyUri = string.Format(
                "otpauth://totp/{0}:{1}?secret={2}&issuer={0}",
                WebUtility.UrlEncode("Marvin"),
                WebUtility.UrlEncode(user.Email),
                secret);

            var vm = new RegisterForMfaViewModel()
            {
                KeyUri    = keyUri,
                Secret    = secret,
                ReturnUrl = returnUrl
            };

            return(View(vm));
        }
        public async Task GetProfileDataAsync(ProfileDataRequestContext context)
        {
            var subjectId     = context.Subject.GetSubjectId();
            var claimsForUser = (await _localUserService.GetUserClaimsBySubjectAsync(subjectId))
                                .ToList();

            var user = await _localUserService.GetUserBySubjectAsync(subjectId);

            var claims = new List <Claim>();

            if (user != null)
            {
                if (!String.IsNullOrEmpty(user?.FirstName))
                {
                    claims.Add(new Claim("given_name", user.FirstName));
                }

                if (!String.IsNullOrEmpty(user?.LastName))
                {
                    claims.Add(new Claim("family_name", user.LastName));
                }

                if (!String.IsNullOrEmpty(user?.UserName))
                {
                    claims.Add(new Claim("name", user.UserName));
                }

                if (!String.IsNullOrEmpty(user?.Email))
                {
                    claims.Add(new Claim("email", user.Email));
                }

                if (context.RequestedClaimTypes.Contains("role"))
                {
                    foreach (var userUserRole in user.Roles)
                    {
                        claims.Add(new Claim("role", userUserRole.Name));
                    }
                }
            }



            context.AddRequestedClaims(claims);
            context.AddRequestedClaims(
                claimsForUser.Select(c => new Claim(c.Type, c.Value)).ToList());
        }
示例#4
0
        public async Task <IActionResult> RegisterForMfa()
        {
            var secret = string.Empty;

            using (var rng = new RNGCryptoServiceProvider())
            {
                byte[] tokenData = new byte[64];
                rng.GetBytes(tokenData);

                var result = new StringBuilder(16);
                for (int i = 0; i < 16; i++)
                {
                    var rnd = BitConverter.ToUInt32(tokenData, i * 4);
                    var idx = rnd % chars.Length;

                    result.Append(chars[idx]);
                }

                secret = result.ToString();
            }

            var subject = User.FindFirst(JwtClaimTypes.Subject)?.Value;
            var user    = await _localUserService.GetUserBySubjectAsync(subject);

            var keyUri = string.Format(
                "otpauth://totp/{0}:{1}?secret={2}&issuer={0}",
                WebUtility.UrlEncode("Marvin"),
                WebUtility.UrlEncode(user.Email),
                secret);

            var vm = new RegisterForMfaViewModel()
            {
                KeyUri = keyUri,
                Secret = secret
            };

            return(View(vm));
        }
示例#5
0
        public async Task <IActionResult> LoginExternal([FromBody] ExternalLoginModel model)
        {
            var resultmodel = new LoginResultModel();

            resultmodel.ReturnUrl = model.ReturnUrl;

            // we will issue the external cookie and then redirect the
            // user back to the external callback, in essence, treating windows
            // auth the same as any other external authentication mechanism
            var props = new AuthenticationProperties()
            {
                RedirectUri = model.ReturnUrl,
                Items       =
                {
                    { "returnUrl", model.ReturnUrl },
                    { "scheme",    model.Scheme    },
                }
            };


            // see if windows auth has already been requested and succeeded
            AuthenticateResult result = await HttpContext.AuthenticateAsync(model.Scheme);

            if (result.Principal != null)
            {
                var authHandler = _authenticationProvider.GetHandler(model.Scheme);

                var factory = authHandler.GetUserFactory(result.Principal);

                var subject = factory.GetSubject();

                var mUser = await _localUserService.GetUserBySubjectAsync(subject);

                if (mUser == null)
                {
                    mUser = factory.BuildUser();

                    await _localUserService.AddUserAsync(mUser);
                }
                else
                {
                    factory.UpdateClaims(mUser);
                    await _usersService.UpdateUserAsync(mUser);
                }

                await HttpContext.SignInAsync(new IdentityServerUser(mUser.Subject)
                {
                    DisplayName        = mUser.UserName,
                    IdentityProvider   = model.Scheme,
                    AuthenticationTime = DateTime.Now
                });

                await HttpContext.SignOutAsync(IdentityServerConstants.ExternalCookieAuthenticationScheme);


                if (_interaction.IsValidReturnUrl(model.ReturnUrl) || Url.IsLocalUrl(model.ReturnUrl))
                {
                    return(Ok(resultmodel.WithStatus(Status.Ok)));
                }

                resultmodel.ReturnUrl = "/";
                return(Ok(resultmodel.WithStatus(Status.Ok)));
            }
            else
            {
                // trigger windows auth
                // since windows auth don't support the redirect uri,
                // this URL is re-triggered when we call challenge
                return(Challenge(model.Scheme));
            }
        }
        public async Task <IActionResult> AdditionalAuthenticationFactor(
            AdditionalAuthenticationFactorViewModel model)
        {
            // check if we are in the context of an authorization request
            var context = await _interaction.GetAuthorizationContextAsync(model.ReturnUrl);

            if (ModelState.IsValid)
            {
                // read identity from the temporary cookie
                var result = await HttpContext.AuthenticateAsync("idsrv.mfa");

                if (result?.Succeeded != true)
                {
                    throw new Exception("MFA authentication error");
                }

                var subject = result.Principal.FindFirst(JwtClaimTypes.Subject)?.Value;

                var user = await _localUserService.GetUserBySubjectAsync(subject);

                var userSecret = await _localUserService.GetUserSecret(subject, "TOTP");

                var authenticator = new TwoStepsAuthenticator.TimeAuthenticator();
                if (!authenticator.CheckCode(userSecret.Secret, model.Totp, user))
                {
                    ModelState.AddModelError("totp", "TOTP is invalid.");
                    return(View(model));
                }

                await _events.RaiseAsync(
                    new UserLoginSuccessEvent(
                        user.Username,
                        user.Subject,
                        user.Username,
                        clientId : context?.Client.ClientId));

                // only set explicit expiration here if user chooses "remember me".
                // otherwise we rely upon expiration configured in cookie middleware.
                AuthenticationProperties props = null;
                if (AccountOptions.AllowRememberLogin && model.RememberLogin)
                {
                    props = new AuthenticationProperties
                    {
                        IsPersistent = true,
                        ExpiresUtc   =
                            DateTimeOffset.UtcNow.Add(AccountOptions.RememberMeLoginDuration)
                    };
                }
                ;

                // delete temporary cookie used during mfa
                await HttpContext.SignOutAsync("idsrv.mfa");

                // issue authentication cookie with subject ID and username
                var isuser = new IdentityServerUser(user.Subject)
                {
                    DisplayName = user.Username
                };

                await HttpContext.SignInAsync(isuser, props);

                if (context != null)
                {
                    if (context.IsNativeClient())
                    {
                        // The client is native, so this change in how to
                        // return the response is for better UX for the end user.
                        return(this.LoadingPage("Redirect", model.ReturnUrl));
                    }

                    // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null
                    return(Redirect(model.ReturnUrl));
                }

                // request for a local page
                if (Url.IsLocalUrl(model.ReturnUrl))
                {
                    return(Redirect(model.ReturnUrl));
                }
                else if (string.IsNullOrEmpty(model.ReturnUrl))
                {
                    return(Redirect("~/"));
                }
                else
                {
                    // user might have clicked on a malicious link - should be logged
                    throw new Exception("invalid return URL");
                }
            }

            return(View(model));
        }