예제 #1
0
        public override Task GrantResourceOwnerCredentials(OAuthGrantResourceOwnerCredentialsContext context)
        => Task.Run(() =>
        {
            var _credentialAuthority = context.OwinContext.GetPerRequestValue <ICredentialAuthentication>(nameof(ICredentialAuthentication));
            var _dataContext         = context.OwinContext.GetPerRequestValue <IDataContext>(nameof(IDataContext));

            #region delete old logons if they exist
            Operation.Try(() =>
            {
                var oldToken = context.Request.Headers.GetValues(WebConstants.OAuthCustomHeaders_OldToken)?.FirstOrDefault() ?? null;
                if (oldToken != null)
                {
                    var logon = _cache.GetOrRefresh <UserLogon>(oldToken);
                    if (logon != null)
                    {
                        logon.Invalidated = true;
                        _dataContext.Store <UserLogon>().Modify(logon, true);
                        _cache.Invalidate(oldToken);
                    }
                }
            })
            #endregion

            #region Verify the user exists
            .Then(opr =>
            {
                return(_dataContext.Store <User>().Query
                       .Where(_u => _u.EntityId == context.UserName)
                       .FirstOrDefault()
                       .ThrowIfNull("invalid user credential")
                       .ThrowIf(_u => _u.Status != (int)AccountStatus.Active, "inactive user account"));
            })
            #endregion

            #region verify credentials with the credential authority
            .Then(opr =>
            {
                _credentialAuthority.VerifyCredential(new Credential
                {
                    OwnerId  = context.UserName,
                    Metadata = CredentialMetadata.Password,
                    Value    = Encoding.UTF8.GetBytes(context.Password)
                })
                .Resolve();
                return(opr.Result);
            })
            #endregion

            #region aggregate the claims that makeup the token
            .Then(opr =>
            {
                var identity = new ClaimsIdentity(context.Options.AuthenticationType);

                //identity.AddClaim(new Claim("user-name", context.UserName));
                identity.AddClaim(new Claim(ClaimTypes.Name, context.UserName));
                identity.AddClaim(new Claim(ClaimTypes.Sid, opr.Result.UId.ToString()));
                identity.AddClaim(new Claim("user-status", opr.Result.Status.ToString()));

                //roles
                _dataContext.Store <UserRole>().Query
                .Where(_ur => _ur.UserId == opr.Result.EntityId)
                .ForAll((_cnt, _next) => identity.AddClaim(new Claim(ClaimTypes.Role, _next.RoleName)));

                context.Validated(new Microsoft.Owin.Security.AuthenticationTicket(identity, null));
            })
            #endregion

            #region if any of the above failed...
            .Error(opr =>
            {
                context.SetError("invalid_grant", opr.Message);
                context.Rejected();
            });
            #endregion
        });