Beispiel #1
0
        public override Task AuthenticateExternalAsync(ExternalAuthenticationContext context)
        {
            using (var userRepository = new UserRepository())
            {
                // is the external provider already linked to an account?
                var existingLinkedUser = userRepository.GetUserForExternalProvider(context.ExternalIdentity.Provider,
                                                                                   context.ExternalIdentity.ProviderId);

                // it is - set as authentication result;
                if (existingLinkedUser != null)
                {
                    context.AuthenticateResult = new AuthenticateResult(
                        existingLinkedUser.Subject,
                        existingLinkedUser.UserClaims.First(c => c.ClaimType == Constants.ClaimTypes.GivenName).ClaimValue,
                        existingLinkedUser.UserClaims.Select <UserClaim, Claim>(uc => new Claim(uc.ClaimType, uc.ClaimValue)),
                        authenticationMethod: Constants.AuthenticationMethods.External,
                        identityProvider: context.ExternalIdentity.Provider);

                    return(Task.FromResult(0));
                }

                // no existing link, get email claim to match user
                var emailClaim = context.ExternalIdentity.Claims.FirstOrDefault(c => c.Type == "email");
                if (emailClaim == null)
                {
                    // return error - we need an email claim to match
                    context.AuthenticateResult = new AuthenticateResult("No email claim available.");
                    return(Task.FromResult(0));
                }

                // find a user with a matching e-mail claim.
                var userWithMatchingEmailClaim = userRepository.GetUserByEmail(emailClaim.Value);

                if (userWithMatchingEmailClaim == null && context.ExternalIdentity.Provider == "windows")
                {
                    // no existing link.  If it's a windows user, we're going to ask for additional
                    // information.
                    context.AuthenticateResult =
                        new AuthenticateResult("~/completeadditionalinformation", context.ExternalIdentity);
                    return(Task.FromResult(0));
                }


                if (userWithMatchingEmailClaim == null)
                {
                    //// return error - we need an existing account
                    //context.AuthenticateResult = new AuthenticateResult("No existing account found.");
                    //return Task.FromResult(0);

                    // create a new account
                    var newUser = new User();
                    newUser.Subject  = Guid.NewGuid().ToString();
                    newUser.IsActive = true;

                    // add the external identity provider as login provider
                    newUser.UserLogins.Add(new UserLogin()
                    {
                        Subject       = newUser.Subject,
                        LoginProvider = context.ExternalIdentity.Provider,
                        ProviderKey   = context.ExternalIdentity.ProviderId
                    });

                    // create a list of claims from the information we got from the external provider
                    // this can be provider-specific
                    if (context.ExternalIdentity.Provider.ToLowerInvariant() == "facebook")
                    {
                        newUser.UserClaims = context.ExternalIdentity
                                             .Claims.Where(c =>
                                                           c.Type.ToLowerInvariant() == Constants.ClaimTypes.GivenName ||
                                                           c.Type.ToLowerInvariant() == Constants.ClaimTypes.FamilyName ||
                                                           c.Type.ToLowerInvariant() == Constants.ClaimTypes.Email)
                                             .Select <Claim, UserClaim>(c => new UserClaim()
                        {
                            Id         = Guid.NewGuid().ToString(),
                            Subject    = newUser.Subject,
                            ClaimType  = c.Type.ToLowerInvariant(),
                            ClaimValue = c.Value
                        }).ToList();
                    }

                    // create a new user with the FreeUser role by default
                    newUser.UserClaims.Add(new UserClaim()
                    {
                        Id         = Guid.NewGuid().ToString(),
                        Subject    = newUser.Subject,
                        ClaimType  = "role",
                        ClaimValue = "FreeUser"
                    });

                    // add the user
                    userRepository.AddUser(newUser);

                    // use this new user
                    context.AuthenticateResult = new AuthenticateResult(
                        newUser.Subject,
                        newUser.UserClaims.First(c => c.ClaimType == Constants.ClaimTypes.GivenName).ClaimValue,
                        newUser.UserClaims.Select <UserClaim, Claim>(uc => new Claim(uc.ClaimType, uc.ClaimValue)),
                        authenticationMethod: Constants.AuthenticationMethods.External,
                        identityProvider: context.ExternalIdentity.Provider);

                    return(Task.FromResult(0));
                }

                // register this external provider for this user account
                userRepository.AddUserLogin(userWithMatchingEmailClaim.Subject,
                                            context.ExternalIdentity.Provider,
                                            context.ExternalIdentity.ProviderId);

                // use this existing account
                context.AuthenticateResult = new AuthenticateResult(
                    userWithMatchingEmailClaim.Subject,
                    userWithMatchingEmailClaim.UserClaims.First(c => c.ClaimType == Constants.ClaimTypes.GivenName).ClaimValue,
                    userWithMatchingEmailClaim.UserClaims.Select <UserClaim, Claim>(uc => new Claim(uc.ClaimType, uc.ClaimValue)),
                    authenticationMethod: Constants.AuthenticationMethods.External,
                    identityProvider: context.ExternalIdentity.Provider);

                return(Task.FromResult(0));
            }
        }
Beispiel #2
0
 /// <summary>
 /// This method gets called when the user uses an external identity provider to authenticate.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <returns></returns>
 public Task AuthenticateExternalAsync(ExternalAuthenticationContext context)
 {
     return(inner.AuthenticateExternalAsync(context));
 }
Beispiel #3
0
 /// <summary>
 /// This method gets called when the user uses an external identity provider to authenticate.
 /// The user's identity from the external provider is passed via the `externalUser` parameter which contains the
 /// provider identifier, the provider's identifier for the user, and the claims from the provider for the external user.
 /// </summary>
 /// <param name="context">The context.</param>
 /// <returns></returns>
 public virtual Task AuthenticateExternalAsync(ExternalAuthenticationContext context)
 {
     return(Task.FromResult(0));
 }
Beispiel #4
0
 public Task AuthenticateExternalAsync(ExternalAuthenticationContext context)
 {
     throw new NotImplementedException();
 }
Beispiel #5
0
 public Task AuthenticateExternalAsync(ExternalAuthenticationContext context)
 {
     return(Task.FromResult(true));
 }
Beispiel #6
0
 public Task AuthenticateExternalAsync(ExternalAuthenticationContext context)
 {
     context.ExternalIdentity.Claims = filter.Filter(context.ExternalIdentity.Provider, context.ExternalIdentity.Claims);
     return(inner.AuthenticateExternalAsync(context));
 }
Beispiel #7
0
 public async Task AuthenticateExternalAsync(ExternalAuthenticationContext context)
 {
 }
        public async Task <IHttpActionResult> ResumeLoginFromRedirect(string resume)
        {
            Logger.Info("Callback requested to resume login from partial login");

            if (resume.IsMissing())
            {
                Logger.Error("no resumeId passed");
                return(RenderErrorPage());
            }

            if (resume.Length > MaxInputParamLength)
            {
                Logger.Error("resumeId length longer than allowed length");
                return(RenderErrorPage());
            }

            var user = await context.GetIdentityFromPartialSignIn();

            if (user == null)
            {
                Logger.Error("no identity from partial login");
                return(RenderErrorPage());
            }

            var type        = GetClaimTypeForResumeId(resume);
            var resumeClaim = user.FindFirst(type);

            if (resumeClaim == null)
            {
                Logger.Error("no claim matching resumeId");
                return(RenderErrorPage());
            }

            var signInId = resumeClaim.Value;

            if (signInId.IsMissing())
            {
                Logger.Error("No signin id found in resume claim");
                return(RenderErrorPage());
            }

            var signInMessage = signInMessageCookie.Read(signInId);

            if (signInMessage == null)
            {
                Logger.Error("No cookie matching signin id found");
                return(RenderErrorPage());
            }

            AuthenticateResult result = null;

            // determine which return path the user is taking -- are they coming from
            // a ExternalProvider partial logon, or not
            var externalProviderClaim = user.FindFirst(Constants.ClaimTypes.ExternalProviderUserId);

            // cleanup the claims from the partial login
            if (user.HasClaim(c => c.Type == Constants.ClaimTypes.PartialLoginRestartUrl))
            {
                user.RemoveClaim(user.FindFirst(Constants.ClaimTypes.PartialLoginRestartUrl));
            }
            if (user.HasClaim(c => c.Type == Constants.ClaimTypes.PartialLoginReturnUrl))
            {
                user.RemoveClaim(user.FindFirst(Constants.ClaimTypes.PartialLoginReturnUrl));
            }
            if (user.HasClaim(c => c.Type == Constants.ClaimTypes.ExternalProviderUserId))
            {
                user.RemoveClaim(user.FindFirst(Constants.ClaimTypes.ExternalProviderUserId));
            }
            if (user.HasClaim(c => c.Type == GetClaimTypeForResumeId(resume)))
            {
                user.RemoveClaim(user.FindFirst(GetClaimTypeForResumeId(resume)));
            }

            if (externalProviderClaim != null)
            {
                Logger.Info("using ExternalProviderUserId to call AuthenticateExternalAsync");

                var provider         = externalProviderClaim.Issuer;
                var providerId       = externalProviderClaim.Value;
                var externalIdentity = new ExternalIdentity
                {
                    Provider   = provider,
                    ProviderId = providerId,
                    Claims     = user.Claims
                };

                Logger.InfoFormat("external user provider: {0}, provider ID: {1}", externalIdentity.Provider, externalIdentity.ProviderId);

                var externalContext = new ExternalAuthenticationContext
                {
                    ExternalIdentity = externalIdentity,
                    SignInMessage    = signInMessage
                };

                await userService.AuthenticateExternalAsync(externalContext);

                result = externalContext.AuthenticateResult;
                if (result == null)
                {
                    Logger.Warn("user service failed to authenticate external identity");

                    var msg = localizationService.GetMessage(MessageIds.NoMatchingExternalAccount);
                    await eventService.RaiseExternalLoginFailureEventAsync(externalIdentity, signInId, signInMessage, msg);

                    return(await RenderLoginPage(signInMessage, signInId, msg));
                }

                if (result.IsError)
                {
                    Logger.WarnFormat("user service returned error message: {0}", result.ErrorMessage);

                    await eventService.RaiseExternalLoginFailureEventAsync(externalIdentity, signInId, signInMessage, result.ErrorMessage);

                    return(await RenderLoginPage(signInMessage, signInId, result.ErrorMessage));
                }

                Logger.Info("External identity successfully validated by user service");

                await eventService.RaiseExternalLoginSuccessEventAsync(externalIdentity, signInId, signInMessage, result);
            }
            else
            {
                // check to see if the resultant user has all the claim types needed to login
                if (!Constants.AuthenticateResultClaimTypes.All(claimType => user.HasClaim(c => c.Type == claimType)))
                {
                    Logger.Error("Missing AuthenticateResultClaimTypes -- rendering error page");
                    return(RenderErrorPage());
                }

                // this is a normal partial login continuation
                Logger.Info("Partial login resume success -- logging user in");

                result = new AuthenticateResult(new ClaimsPrincipal(user));

                await eventService.RaisePartialLoginCompleteEventAsync(result.User.Identities.First(), signInId, signInMessage);
            }

            return(await SignInAndRedirectAsync(signInMessage, signInId, result));
        }
 public override Task AuthenticateExternalAsync(ExternalAuthenticationContext context)
 {
     return(Task.FromResult <AuthenticateResult>(null));
 }
Beispiel #10
0
 public Task AuthenticateExternalAsync(ExternalAuthenticationContext context)
 {
     context.AuthenticateResult = null;
     return(Task.FromResult(0));
 }
        public override async Task AuthenticateExternalAsync(ExternalAuthenticationContext context)
        {
            var externalIdentity = context.ExternalIdentity;

            context.AuthenticateResult = await GetAppropriateAuthenticationResult(externalIdentity);
        }
Beispiel #12
0
 protected virtual async Task <string> GetInternalUserId(ExternalAuthenticationContext context)
 {
     throw new NotImplementedException();
 }
Beispiel #13
0
 public async Task AuthenticateExternalAsync(ExternalAuthenticationContext context)
 {
     await this.innerUserService.AuthenticateExternalAsync(context);
 }
Beispiel #14
0
 public sealed override Task AuthenticateExternalAsync(ExternalAuthenticationContext context)
 {
     return(AuthenticateExternalAsync(context, OwinContext.Request.CallCancelled));
 }
Beispiel #15
0
 protected virtual Task <string> GetInternalUserId(ExternalAuthenticationContext context, CancellationToken cancellationToken)
 {
     throw new NotImplementedException();
 }
        public async Task <IHttpActionResult> LoginExternalCallback(string error = null)
        {
            Logger.Info("Callback invoked from external identity provider");

            if (error.IsPresent())
            {
                if (error.Length > MaxInputParamLength)
                {
                    error = error.Substring(0, MaxInputParamLength);
                }

                Logger.ErrorFormat("External identity provider returned error: {0}", error);
                await eventService.RaiseExternalLoginErrorEventAsync(error);

                return(RenderErrorPage(String.Format(localizationService.GetMessage(MessageIds.ExternalProviderError), error)));
            }

            var signInId = await context.GetSignInIdFromExternalProvider();

            if (signInId.IsMissing())
            {
                Logger.Info("No signin id passed");
                return(HandleNoSignin());
            }

            var signInMessage = signInMessageCookie.Read(signInId);

            if (signInMessage == null)
            {
                Logger.Info("No cookie matching signin id found");
                return(HandleNoSignin());
            }

            var user = await context.GetIdentityFromExternalProvider();

            if (user == null)
            {
                Logger.Error("no identity from external identity provider");
                return(await RenderLoginPage(signInMessage, signInId, localizationService.GetMessage(MessageIds.NoMatchingExternalAccount)));
            }

            var externalIdentity = ExternalIdentity.FromClaims(user.Claims);

            if (externalIdentity == null)
            {
                var claims = user.Claims.Select(x => new { x.Type, x.Value });
                Logger.ErrorFormat("no subject or unique identifier claims from external identity provider. Claims provided:\r\n{0}", LogSerializer.Serialize(claims));
                return(await RenderLoginPage(signInMessage, signInId, localizationService.GetMessage(MessageIds.NoMatchingExternalAccount)));
            }

            Logger.InfoFormat("external user provider: {0}, provider ID: {1}", externalIdentity.Provider, externalIdentity.ProviderId);

            var externalContext = new ExternalAuthenticationContext
            {
                ExternalIdentity = externalIdentity,
                SignInMessage    = signInMessage
            };

            await userService.AuthenticateExternalAsync(externalContext);

            var authResult = externalContext.AuthenticateResult;

            if (authResult == null)
            {
                Logger.Warn("user service failed to authenticate external identity");

                var msg = localizationService.GetMessage(MessageIds.NoMatchingExternalAccount);
                await eventService.RaiseExternalLoginFailureEventAsync(externalIdentity, signInId, signInMessage, msg);

                return(await RenderLoginPage(signInMessage, signInId, msg));
            }

            if (authResult.IsError)
            {
                Logger.WarnFormat("user service returned error message: {0}", authResult.ErrorMessage);

                await eventService.RaiseExternalLoginFailureEventAsync(externalIdentity, signInId, signInMessage, authResult.ErrorMessage);

                return(await RenderLoginPage(signInMessage, signInId, authResult.ErrorMessage));
            }

            Logger.Info("External identity successfully validated by user service");

            await eventService.RaiseExternalLoginSuccessEventAsync(externalIdentity, signInId, signInMessage, authResult);

            return(await SignInAndRedirectAsync(signInMessage, signInId, authResult));
        }
Beispiel #17
0
 public sealed override Task AuthenticateExternalAsync(ExternalAuthenticationContext context)
 {
     return(AuthenticateExternalAsync(context, CurrentCancellationToken));
 }
Beispiel #18
0
 protected virtual Task <BitJwtToken> ExternalLogin(ExternalAuthenticationContext context, CancellationToken cancellationToken)
 {
     throw new NotImplementedException();
 }
 public override Task AuthenticateExternalAsync(ExternalAuthenticationContext ctx)
 {
     return(base.AuthenticateExternalAsync(ctx));
 }