public Task<AuthenticateResult> AuthenticateExternalAsync(ExternalIdentity externalUser, SignInMessage message)
        {
            // look for the user in our local identity system from the external identifiers
            var user = Users.SingleOrDefault(x => x.Provider == externalUser.Provider && x.ProviderID == externalUser.ProviderId);
            string name = "Unknown";
            if (user == null)
            {
                // new user, so add them here
                var nameClaim = externalUser.Claims.First(x => x.Type == Constants.ClaimTypes.Name);
                if (nameClaim != null) name = nameClaim.Value;

                user = new CustomUser { 
                    Subject = Guid.NewGuid().ToString(),
                    Provider = externalUser.Provider,
                    ProviderID = externalUser.ProviderId,
                    Claims = new List<Claim> { new Claim(Constants.ClaimTypes.Name, name) }
                };
                Users.Add(user);
            }

            name = user.Claims.First(x => x.Type == Constants.ClaimTypes.Name).Value;

            if (user.IsRegistered)
            {
                // user is registered so continue
                return Task.FromResult<AuthenticateResult>(new AuthenticateResult(user.Subject, name, identityProvider:user.Provider));
            }
            else
            {
                // user not registered so we will issue a partial login and redirect them to our registration page
                return Task.FromResult<AuthenticateResult>(new AuthenticateResult("/core/externalregistration", user.Subject, name, identityProvider: user.Provider));
            }
        }
        public Task<ExternalAuthenticateResult> AuthenticateExternalAsync(string subject, ExternalIdentity user)
        {
            if (user == null)
            {
                return Task.FromResult<ExternalAuthenticateResult>(null);
            }

            var claims = user.Claims;
            if (claims == null)
            {
                return Task.FromResult<ExternalAuthenticateResult>(null);
            }

            var name = claims.FirstOrDefault(x => x.Type == ClaimTypes.Name || x.Type == Constants.ClaimTypes.Name);
            if (name == null)
            {
                return null;
            }

            return Task.FromResult(new ExternalAuthenticateResult(user.Provider.Name, Guid.NewGuid().ToString("D"), name.Value));
        }
        /// <summary>
        /// This method gets called when the user uses an external identity provider to authenticate.
        /// </summary>
        /// <param name="externalUser">The external user.</param>
        /// <param name="message">The signin message.</param>
        /// <returns>
        /// The authentication result.
        /// </returns>
        public virtual Task<AuthenticateResult> AuthenticateExternalAsync(ExternalIdentity externalUser, SignInMessage message)
        {
            var query =
                from u in _users
                where
                    u.Provider == externalUser.Provider &&
                    u.ProviderId == externalUser.ProviderId
                select u;

            var user = query.SingleOrDefault();
            if (user == null)
            {
                string displayName;

                var name = externalUser.Claims.FirstOrDefault(x => x.Type == Constants.ClaimTypes.Name);
                if (name == null)
                {
                    displayName = externalUser.ProviderId;
                }
                else
                {
                    displayName = name.Value;
                }

                user = new User
                {
                    Subject = RandomString(16),
                    Provider = externalUser.Provider,
                    ProviderId = externalUser.ProviderId,
                    Username = displayName,
                    Claims = externalUser.Claims
                };
                _users.Add(user);
            }

            //var p = IdentityServerPrincipal.Create(user.Subject, GetDisplayName(user), Constants.AuthenticationMethods.External, user.Provider);
            //var result = new AuthenticateResult(p);
            //return Task.FromResult(result);
            return Task.FromResult(new AuthenticateResult("/core/account/eula", user.Subject, GetDisplayName(user)));
        }
Esempio n. 4
0
        public AuthenticateResult(string redirectPath, ExternalIdentity externalId)
        {
            if (redirectPath.IsMissing())
            {
                throw new ArgumentNullException("redirectPath");
            }
            if (!redirectPath.StartsWith("~/") && !redirectPath.StartsWith("/"))
            {
                throw new ArgumentException("redirectPath must start with / or ~/");
            }
            if (externalId == null)
            {
                throw new ArgumentNullException("externalId");
            }

            this.PartialSignInRedirectPath = redirectPath;

            var id = new ClaimsIdentity(externalId.Claims, Constants.PartialSignInAuthenticationType);

            // we're keeping the external provider info for the partial signin so we can re-execute AuthenticateExternalAsync
            // once the user is re-directed back into identityserver from the external redirect
            id.AddClaim(new Claim(Constants.ClaimTypes.ExternalProviderUserId, externalId.ProviderId, ClaimValueTypes.String, externalId.Provider));
            User = new ClaimsPrincipal(id);
        }
        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();
            }

            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(localizationService.GetMessage(MessageIds.NoSignInCookie));
            }

            // check to see if the partial login has all the claim types needed to login
            AuthenticateResult result = null;
            if (Constants.AuthenticateResultClaimTypes.All(claimType => user.HasClaim(claimType)))
            {
                Logger.Info("Authentication claims found -- logging user in");
                
                // the user/subject was known, so pass thru (without the redirect claims)
                if (user.HasClaim(Constants.ClaimTypes.PartialLoginReturnUrl))
                {
                    user.RemoveClaim(user.FindFirst(Constants.ClaimTypes.PartialLoginReturnUrl));
                }
                if (user.HasClaim(Constants.ClaimTypes.ExternalProviderUserId))
                {
                    user.RemoveClaim(user.FindFirst(Constants.ClaimTypes.ExternalProviderUserId));
                }
                if (user.HasClaim(GetClaimTypeForResumeId(resume)))
                {
                    user.RemoveClaim(user.FindFirst(GetClaimTypeForResumeId(resume)));
                }
                
                result = new AuthenticateResult(new ClaimsPrincipal(user));

                eventService.RaisePartialLoginCompleteEvent(user, signInId, signInMessage);
            }
            else
            {
                Logger.Info("Authentication claims not found -- looking for ExternalProviderUserId to call AuthenticateExternalAsync");
                
                // the user was not known, we need to re-execute AuthenticateExternalAsync
                // to obtain a subject to proceed
                var externalProviderClaim = user.FindFirst(Constants.ClaimTypes.ExternalProviderUserId);
                if (externalProviderClaim == null)
                {
                    Logger.Error("No ExternalProviderUserId claim found -- rendering error page");
                    return RenderErrorPage();
                }

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

                result = await userService.AuthenticateExternalAsync(externalId, signInMessage);

                if (result == null)
                {
                    Logger.Warn("user service failed to authenticate external identity");
                    
                    var msg = localizationService.GetMessage(MessageIds.NoMatchingExternalAccount);
                    eventService.RaiseExternalLoginFailureEvent(externalId, signInId, signInMessage, msg);
                    
                    return await RenderLoginPage(signInMessage, signInId, msg);
                }

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

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

                eventService.RaiseExternalLoginSuccessEvent(externalId, signInId, signInMessage, result);
            }

            return SignInAndRedirect(signInMessage, signInId, result);
        }
        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();
            }

            var user = await 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 cookie = new MessageCookie<SignInMessage>(Request.GetOwinContext(), this._options);
            var signInMessage = cookie.Read(signInId);
            if (signInMessage == null)
            {
                Logger.Error("No cookie matching signin id found");
                return RenderErrorPage();
            }

            AuthenticateResult result = null;
            var externalProviderClaim = user.FindFirst(Constants.ClaimTypes.ExternalProviderUserId);
            if (externalProviderClaim == null)
            {
                // the user/subject was known, so pass thru (without the redirect claims)
                user.RemoveClaim(user.FindFirst(Constants.ClaimTypes.PartialLoginReturnUrl));
                user.RemoveClaim(user.FindFirst(GetClaimTypeForResumeId(resume)));
                result = new AuthenticateResult(new ClaimsPrincipal(user));
            }
            else
            {
                // the user was not known, we need to re-execute AuthenticateExternalAsync
                // to obtain a subject to proceed
                var provider = externalProviderClaim.Issuer;
                var providerId = externalProviderClaim.Value;
                var externalId = new ExternalIdentity
                {
                    Provider = provider,
                    ProviderId = providerId,
                    Claims = user.Claims
                };

                result = await _userService.AuthenticateExternalAsync(externalId);

                if (result == null)
                {
                    Logger.Warn("user service failed to authenticate external identity");
                    return await RenderLoginPage(signInMessage, signInId, Messages.NoMatchingExternalAccount);
                }

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

            return SignInAndRedirect(signInMessage, signInId, result);
        }
 public Task<AuthenticateResult> AuthenticateExternalAsync(ExternalIdentity externalUser, SignInMessage message)
 {
     return Task.FromResult<AuthenticateResult>(null);
 }
 /// <summary>
 /// This method gets called when the user uses an external identity provider to authenticate.
 /// </summary>
 /// <param name="externalUser">The external user.</param>
 /// <param name="message">The signin message.</param>
 /// <returns>
 /// The authentication result.
 /// </returns>
 public Task<AuthenticateResult> AuthenticateExternalAsync(ExternalIdentity externalUser, SignInMessage message)
 {
     return inner.AuthenticateExternalAsync(externalUser, message);
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="AuthenticateResult" /> class. This
        /// version of the constructor indicates a partial login (with a redirect) without
        /// knowledge of the subject claim.
        /// </summary>
        /// <param name="redirectPath">The redirect path. This should be relative to the 
        /// current web server. The <c>"~/"</c> prefix is supported to allow application-relative
        /// paths to be used (e.g. "~/path").
        /// </param>
        /// <param name="externalId">The external identifier that represents the external identity
        /// provider the partial login is created from. This will be re-presented to correlate the request
        /// when the user resumes from the redirect.</param>
        /// <exception cref="System.ArgumentNullException">
        /// redirectPath
        /// or
        /// externalId
        /// </exception>
        /// <exception cref="System.ArgumentException">redirectPath must start with / or ~/</exception>
        public AuthenticateResult(string redirectPath, ExternalIdentity externalId)
        {
            if (redirectPath.IsMissing()) throw new ArgumentNullException("redirectPath");
            if (!redirectPath.StartsWith("~/") && !redirectPath.StartsWith("/"))
            {
                throw new ArgumentException("redirectPath must start with / or ~/");
            }
            if (externalId == null) throw new ArgumentNullException("externalId");

            this.PartialSignInRedirectPath = redirectPath;

            var id = new ClaimsIdentity(externalId.Claims, Constants.PartialSignInAuthenticationType);
            // we're keeping the external provider info for the partial signin so we can re-execute AuthenticateExternalAsync
            // once the user is re-directed back into identityserver from the external redirect
            id.AddClaim(new Claim(Constants.ClaimTypes.ExternalProviderUserId, externalId.ProviderId, ClaimValueTypes.String, externalId.Provider));
            User = new ClaimsPrincipal(id);
        }
 public Task<AuthenticateResult> AuthenticateExternalAsync(ExternalIdentity user)
 {
     throw new NotImplementedException();
 }
        /// <summary>
        /// This method gets called when the user uses an external identity provider to authenticate.
        /// </summary>
        /// <param name="externalUser">The external user.</param>
        /// <returns>
        /// The authentication result.
        /// </returns>
        public virtual Task<AuthenticateResult> AuthenticateExternalAsync(ExternalIdentity externalUser)
        {
            var query =
                from u in _users
                where
                    u.Provider == externalUser.Provider &&
                    u.ProviderId == externalUser.ProviderId
                select u;

            var user = query.SingleOrDefault();
            if (user == null)
            {
                var name = externalUser.Claims.FirstOrDefault(x => x.Type == Constants.ClaimTypes.Name);
                if (name == null)
                {
                    return Task.FromResult<AuthenticateResult>(null);
                }

                user = new InMemoryUser
                {
                    Subject = CryptoRandom.CreateUniqueId(),
                    Provider = externalUser.Provider,
                    ProviderId = externalUser.ProviderId,
                    Username = name.Value,
                    Claims = externalUser.Claims
                };
                _users.Add(user);
            }

            var p = IdentityServerPrincipal.Create(user.Subject, GetDisplayName(user), Constants.AuthenticationMethods.External, user.Provider);
            var result = new AuthenticateResult(p);
            return Task.FromResult(result);
        }
Esempio n. 12
0
 public Task<AuthenticateResult> AuthenticateExternalAsync(ExternalIdentity externalUser, SignInMessage message)
 {
     throw new NotImplementedException();
 }
 public Task<AuthenticateResult> AuthenticateExternalAsync(ExternalIdentity externalUser, SignInMessage message)
 {
     externalUser.Claims = filter.Filter(externalUser.Provider, externalUser.Claims);
     return inner.AuthenticateExternalAsync(externalUser, message);
 }
Esempio n. 14
0
 public Task <ExternalAuthenticateResult> AuthenticateExternalAsync(string subject, Thinktecture.IdentityServer.Core.Models.ExternalIdentity user)
 {
     throw new NotImplementedException();
 }