/// <summary>Creates an access token.</summary>
        /// <param name="clientId">Identifier for the client.</param>
        /// <param name="redirectUri">URI of the redirect.</param>
        /// <param name="userPrincipal">The user principal.</param>
        /// <param name="scope">The scope.</param>
        /// <param name="expireTime">The expire time.</param>
        /// <returns>The new access token.</returns>
        public async Task <TokenCreationResult <IAccessToken> > CreateAccessToken(
            string clientId,
            string redirectUri,
            ISentinelPrincipal userPrincipal,
            IEnumerable <string> scope,
            DateTimeOffset expireTime)
        {
            string token;
            var    hashedToken = this.cryptoProvider.CreateHash(out token, 512);

            // Add expire claim
            userPrincipal.Identity.AddClaim(new SentinelClaim(ClaimType.Expiration, expireTime.ToUnixTime().ToString()));

            var accessToken = new AccessToken()
            {
                ClientId    = clientId,
                RedirectUri = redirectUri,
                Subject     = userPrincipal.Identity.Name,
                Scope       = scope,
                Token       = hashedToken,
                Ticket      = this.principalProvider.Encrypt(userPrincipal, token),
                ValidTo     = expireTime
            };

            return(new TokenCreationResult <IAccessToken>(token, accessToken));
        }
        /// <summary>Creates an authorization code.</summary>
        /// <param name="clientId">Identifier for the client.</param>
        /// <param name="redirectUri">The redirect URI.</param>
        /// <param name="userPrincipal">The user principal.</param>
        /// <param name="scope">The scope.</param>
        /// <param name="expireTime">The expire time.</param>
        /// <returns>An object containing the new access token entity and the hashed token.</returns>
        public async Task <TokenCreationResult <IAuthorizationCode> > CreateAuthorizationCode(
            string clientId,
            string redirectUri,
            ISentinelPrincipal userPrincipal,
            IEnumerable <string> scope,
            DateTimeOffset expireTime)
        {
            string code;
            var    hashedCode = this.cryptoProvider.CreateHash(out code, 256);

            // Add expire claim
            userPrincipal.Identity.AddClaim(new SentinelClaim(ClaimType.Expiration, expireTime.ToUnixTime().ToString()));

            var authorizationCode = new AuthorizationCode()
            {
                ClientId    = clientId,
                RedirectUri = redirectUri,
                Subject     = userPrincipal.Identity.Name,
                Scope       = scope,
                Code        = hashedCode,
                Ticket      = this.principalProvider.Encrypt(userPrincipal, code),
                ValidTo     = expireTime
            };

            return(new TokenCreationResult <IAuthorizationCode>(code, authorizationCode));
        }
Beispiel #3
0
        /// <summary>Creates an access token.</summary>
        /// <param name="clientId">Identifier for the client.</param>
        /// <param name="redirectUri">The redirect URI.</param>
        /// <param name="userPrincipal">The user principal.</param>
        /// <param name="scope">The scope.</param>
        /// <param name="expireTime">The expire time.</param>
        /// <returns>An object containing the new access token entity and the hashed token.</returns>
        public async Task <TokenCreationResult <IAccessToken> > CreateAccessToken(
            string clientId,
            string redirectUri,
            ISentinelPrincipal userPrincipal,
            IEnumerable <string> scope,
            DateTimeOffset expireTime)
        {
            // Create token
            string token;
            var    hashedToken = this.configuration.CryptoProvider.CreateHash(out token, 512);

            // Create access token hash
            var tokenHash = Convert.FromBase64String(this.configuration.CryptoProvider.CreateHash(token, false));

            // Add extra claims
            userPrincipal.Identity.RemoveClaim(x => x.Type == JwtClaimType.Subject);
            userPrincipal.Identity.RemoveClaim(x => x.Type == JwtClaimType.AccessTokenHash);
            userPrincipal.Identity.AddClaim(JwtClaimType.Subject, userPrincipal.Identity.Name);
            userPrincipal.Identity.AddClaim(JwtClaimType.AccessTokenHash, Convert.ToBase64String(tokenHash.Take(16).ToArray()));

            var jwt = new JwtSecurityToken(
                this.configuration.Issuer.AbsoluteUri,
                clientId,
                userPrincipal.Identity.Claims.ToClaims(),
                DateTime.UtcNow,
                expireTime.UtcDateTime,
                this.configuration.SigningCredentials);

            var idToken = this.tokenHandler.WriteToken(jwt);

            var accessToken = new AccessToken()
            {
                ClientId    = clientId,
                RedirectUri = redirectUri,
                Subject     = userPrincipal.Identity.Name,
                Scope       = scope,
                Token       = hashedToken,
                Ticket      = idToken,
                ValidTo     = expireTime
            };

            return(new TokenCreationResult <IAccessToken>(token, accessToken));
        }
Beispiel #4
0
        /// <summary>Creates an authorization code.</summary>
        /// <param name="clientId">Identifier for the client.</param>
        /// <param name="redirectUri">The redirect URI.</param>
        /// <param name="userPrincipal">The user principal.</param>
        /// <param name="scope">The scope.</param>
        /// <param name="expireTime">The expire time.</param>
        /// <returns>An object containing the new access token entity and the hashed token.</returns>
        public async Task <TokenCreationResult <IAuthorizationCode> > CreateAuthorizationCode(
            string clientId,
            string redirectUri,
            ISentinelPrincipal userPrincipal,
            IEnumerable <string> scope,
            DateTimeOffset expireTime)
        {
            string code;
            var    hashedCode = this.configuration.CryptoProvider.CreateHash(out code, 256);

            // Create a separate authorization code hash
            var codeHash = Convert.FromBase64String(this.configuration.CryptoProvider.CreateHash(code, false));

            // Add extra claims
            userPrincipal.Identity.RemoveClaim(x => x.Type == JwtClaimType.Subject);
            userPrincipal.Identity.RemoveClaim(x => x.Type == JwtClaimType.AuthorizationCodeHash);
            userPrincipal.Identity.AddClaim(JwtClaimType.Subject, userPrincipal.Identity.Name);
            userPrincipal.Identity.AddClaim(JwtClaimType.AuthorizationCodeHash, Convert.ToBase64String(codeHash.Take(16).ToArray()));

            var jwt = new JwtSecurityToken(
                this.configuration.Issuer.AbsoluteUri,
                clientId,
                userPrincipal.Identity.Claims.ToClaims(),
                DateTime.UtcNow,
                expireTime.UtcDateTime,
                this.configuration.SigningCredentials);

            var ticket = this.tokenHandler.WriteToken(jwt);

            var authorizationCode = new AuthorizationCode()
            {
                ClientId    = clientId,
                RedirectUri = redirectUri,
                Subject     = userPrincipal.Identity.Name,
                Scope       = scope,
                Code        = hashedCode,
                Ticket      = ticket,
                ValidTo     = expireTime
            };

            return(new TokenCreationResult <IAuthorizationCode>(code, authorizationCode));
        }
Beispiel #5
0
        /// <summary>Creates a refresh token.</summary>
        /// <param name="clientId">Identifier for the client.</param>
        /// <param name="redirectUri">The redirect URI.</param>
        /// <param name="userPrincipal">The user principal.</param>
        /// <param name="scope">The scope.</param>
        /// <param name="expireTime">The expire time.</param>
        /// <returns>An object containing the new access token entity and the hashed token.</returns>
        public async Task <TokenCreationResult <IRefreshToken> > CreateRefreshToken(
            string clientId,
            string redirectUri,
            ISentinelPrincipal userPrincipal,
            IEnumerable <string> scope,
            DateTimeOffset expireTime)
        {
            string token;
            var    hashedToken = this.configuration.CryptoProvider.CreateHash(out token, 2048);

            var refreshToken = new RefreshToken()
            {
                ClientId    = clientId,
                RedirectUri = redirectUri,
                Subject     = userPrincipal.Identity.Name,
                Scope       = scope,
                Token       = hashedToken,
                ValidTo     = expireTime
            };

            return(new TokenCreationResult <IRefreshToken>(token, refreshToken));
        }
        /// <summary>Creates a refresh token.</summary>
        /// <param name="userPrincipal">The principal.</param>
        /// <param name="expire">The expire time.</param>
        /// <param name="clientId">The client identifier.</param>
        /// <param name="redirectUri">The redirect URI.</param>
        /// <param name="scope">The scope.</param>
        /// <returns>A refresh token.</returns>
        public override async Task<string> CreateRefreshTokenAsync(ISentinelPrincipal userPrincipal, TimeSpan expire, string clientId, string redirectUri, IEnumerable<string> scope)
        {
            if (!userPrincipal.Identity.IsAuthenticated)
            {
                this.logger.ErrorFormat("The specified principal is not authenticated");

                return string.Empty;
            }

            // Delete all expired refresh tokens
            await this.TokenRepository.DeleteRefreshTokens(DateTime.UtcNow);

            // Remove unnecessary claims from principal
            userPrincipal.Identity.RemoveClaim(x => x.Type == ClaimType.AccessToken || x.Type == ClaimType.RefreshToken);

            // Add scope claims
            if (scope != null)
            {
                userPrincipal.Identity.AddClaim(scope.Select(x => new SentinelClaim(ClaimType.Scope, x)).ToArray());
            }

            this.logger.DebugFormat("Creating refresh token for client '{0}', redirect uri '{1}' and user '{2}'", clientId, redirectUri, userPrincipal.Identity.Name);

            // Create new refresh token
            string token;
            var hashedToken = this.CryptoProvider.CreateHash(out token, 2048);

            var refreshToken = this.TokenFactory.CreateRefreshToken(clientId, redirectUri, userPrincipal.Identity.Name, scope, hashedToken, DateTime.UtcNow.Add(expire));

            // Add refresh token to database
            var result = await this.TokenRepository.InsertRefreshToken(refreshToken);

            if (result != null)
            {
                this.logger.DebugFormat("Successfully created and stored refresh token");

                return token;
            }

            this.logger.ErrorFormat("Unable to create and/or store refresh token");

            return string.Empty;
        }
        /// <summary>Generates an authorization code for the specified client.</summary>
        /// <exception cref="ArgumentException">
        /// Thrown when one or more arguments have unsupported or illegal values.
        /// </exception>
        /// <param name="userPrincipal">The user principal.</param>
        /// <param name="expire">The expire time.</param>
        /// <param name="redirectUri">The redirect URI.</param>
        /// <param name="scope">The scope.</param>
        /// <returns>An authorization code.</returns>
        public override async Task<string> CreateAuthorizationCodeAsync(ISentinelPrincipal userPrincipal, TimeSpan expire, string redirectUri, IEnumerable<string> scope)
        {
            if (!userPrincipal.Identity.IsAuthenticated)
            {
                this.logger.ErrorFormat("The specified user is not authenticated");

                return string.Empty;
            }

            var client = userPrincipal.Identity.Claims.FirstOrDefault(x => x.Type == ClaimType.Client);

            if (client == null || string.IsNullOrEmpty(client.Value))
            {
                throw new ArgumentException("The specified principal does not have a valid client identifier", "userPrincipal");
            }

            // Delete all expired authorization codes
            await this.TokenRepository.DeleteAuthorizationCodes(DateTime.UtcNow);

            // Remove unnecessary claims from principal
            userPrincipal.Identity.RemoveClaim(x => x.Type == ClaimType.AccessToken || x.Type == ClaimType.RefreshToken);

            // Add scope claims
            if (scope != null)
            {
                userPrincipal.Identity.AddClaim(scope.Select(x => new SentinelClaim(ClaimType.Scope, x)).ToArray());
            }

            // Create and store authorization code for future use
            this.logger.DebugFormat("Creating authorization code for client '{0}', redirect uri '{1}' and user '{2}'", client, redirectUri, userPrincipal.Identity.Name);

            string code;
            var hashedCode = this.CryptoProvider.CreateHash(out code, 256);

            var authorizationCode = this.TokenFactory.CreateAuthorizationCode(
                client.Value,
                redirectUri,
                userPrincipal.Identity.Name,
                scope,
                hashedCode,
                this.PrincipalProvider.Encrypt(userPrincipal, code),
                DateTime.UtcNow.Add(expire));

            // Add authorization code to database
            var result = await this.TokenRepository.InsertAuthorizationCode(authorizationCode);

            if (result != null)
            {
                this.logger.DebugFormat("Successfully created and stored authorization code");

                return code;
            }

            this.logger.ErrorFormat("Unable to create and/or store authorization code");

            return string.Empty;
        }
 /// <summary>Initializes a new instance of the <see cref="TokenValidationResult{T}" /> class.</summary>
 /// <param name="principal">The principal.</param>
 /// <param name="entity">The entity.</param>
 public TokenValidationResult(ISentinelPrincipal principal, T entity)
 {
     this.Principal = principal;
     this.Entity    = entity;
 }
Beispiel #9
0
        /// <summary>
        /// Encrypts the specified principal.
        /// </summary>
        /// <param name="principal">The principal.</param>
        /// <param name="key">The key.</param>
        /// <returns>The encrypted principal.</returns>
        public string Encrypt(ISentinelPrincipal principal, string key)
        {
            var s = JsonConvert.SerializeObject(principal);

            return(this.cryptoProvider.Encrypt(s, key));
        }
        /// <summary>
        /// Encrypts the specified principal.
        /// </summary>
        /// <param name="principal">The principal.</param>
        /// <param name="key">The key.</param>
        /// <returns>The encrypted principal.</returns>
        public string Encrypt(ISentinelPrincipal principal, string key)
        {
            var s = JsonConvert.SerializeObject(principal);

            return this.cryptoProvider.Encrypt(s, key);
        }
 /// <summary>Creates a refresh token.</summary>
 /// <param name="userPrincipal">The principal.</param>
 /// <param name="expire">The expire time.</param>
 /// <param name="clientId">The client id.</param>
 /// <param name="redirectUri">The redirect URI.</param>
 /// <param name="scope">The scope.</param>
 /// <returns>The token creation result.</returns>
 public abstract Task <TokenCreationResult <IRefreshToken> > CreateRefreshTokenAsync(ISentinelPrincipal userPrincipal, TimeSpan expire, string clientId, string redirectUri, IEnumerable <string> scope);
 /// <summary>Generates an authorization code for the specified client.</summary>
 /// <param name="userPrincipal">The user principal.</param>
 /// <param name="expire">The expire time.</param>
 /// <param name="redirectUri">The redirect URI.</param>
 /// <param name="scope">The scope.</param>
 /// <returns>The token creation result.</returns>
 public abstract Task <TokenCreationResult <IAuthorizationCode> > CreateAuthorizationCodeAsync(ISentinelPrincipal userPrincipal, TimeSpan expire, string redirectUri, IEnumerable <string> scope);
 /// <summary>Creates a refresh token.</summary>
 /// <param name="userPrincipal">The principal.</param>
 /// <param name="expire">The expire time.</param>
 /// <param name="clientId">The client id.</param>
 /// <param name="redirectUri">The redirect URI.</param>
 /// <param name="scope">The scope.</param>
 /// <returns>A refresh token.</returns>
 public abstract Task<string> CreateRefreshTokenAsync(ISentinelPrincipal userPrincipal, TimeSpan expire, string clientId, string redirectUri, IEnumerable<string> scope);
 /// <summary>Generates an authorization code for the specified client.</summary>
 /// <param name="userPrincipal">The user principal.</param>
 /// <param name="expire">The expire time.</param>
 /// <param name="redirectUri">The redirect URI.</param>
 /// <param name="scope">The scope.</param>
 /// <returns>An authorization code.</returns>
 public abstract Task<string> CreateAuthorizationCodeAsync(ISentinelPrincipal userPrincipal, TimeSpan expire, string redirectUri, IEnumerable<string> scope);
Beispiel #15
0
        /// <summary>Creates a refresh token.</summary>
        /// <param name="userPrincipal">The principal.</param>
        /// <param name="expire">The expire time.</param>
        /// <param name="clientId">The client identifier.</param>
        /// <param name="redirectUri">The redirect URI.</param>
        /// <param name="scope">The scope.</param>
        /// <returns>A refresh token.</returns>
        public override async Task <TokenCreationResult <IRefreshToken> > CreateRefreshTokenAsync(ISentinelPrincipal userPrincipal, TimeSpan expire, string clientId, string redirectUri, IEnumerable <string> scope)
        {
            if (!userPrincipal.Identity.IsAuthenticated)
            {
                this.logger.Error("The specified principal is not authenticated");

                return(null);
            }

            // Delete all expired refresh tokens
            await this.TokenRepository.DeleteRefreshTokens(DateTimeOffset.UtcNow);

            // Add scope claims
            if (scope != null)
            {
                userPrincipal.Identity.AddClaim(scope.Where(x => !userPrincipal.Identity.HasClaim(ClaimType.Scope, x)).Select(x => new SentinelClaim(ClaimType.Scope, x)).ToArray());
            }

            this.logger.DebugFormat("Creating refresh token for client '{0}', redirect uri '{1}' and user '{2}'", clientId, redirectUri, userPrincipal.Identity.Name);

            var createResult =
                await
                this.TokenProvider.CreateRefreshToken(
                    clientId,
                    redirectUri,
                    userPrincipal,
                    scope,
                    DateTimeOffset.UtcNow.Add(expire));

            // Add refresh token to database
            var insertResult = await this.TokenRepository.InsertRefreshToken(createResult.Entity);

            if (insertResult != null)
            {
                this.logger.Debug("Successfully created and stored refresh token");

                return(new TokenCreationResult <IRefreshToken>(createResult.Token, insertResult));
            }

            this.logger.Error("Unable to create and/or store refresh token");

            return(null);
        }
Beispiel #16
0
        /// <summary>Generates an authorization code for the specified client.</summary>
        /// <exception cref="ArgumentException">
        /// Thrown when one or more arguments have unsupported or illegal values.
        /// </exception>
        /// <param name="userPrincipal">The user principal.</param>
        /// <param name="expire">The expire time.</param>
        /// <param name="redirectUri">The redirect URI.</param>
        /// <param name="scope">The scope.</param>
        /// <returns>An authorization code.</returns>
        public override async Task <TokenCreationResult <IAuthorizationCode> > CreateAuthorizationCodeAsync(ISentinelPrincipal userPrincipal, TimeSpan expire, string redirectUri, IEnumerable <string> scope)
        {
            if (!userPrincipal.Identity.IsAuthenticated)
            {
                this.logger.Error("The specified user is not authenticated");

                return(null);
            }

            var client = userPrincipal.Identity.Claims.FirstOrDefault(x => x.Type == ClaimType.Client);

            if (client == null || string.IsNullOrEmpty(client.Value))
            {
                throw new ArgumentException("The specified principal does not have a valid client identifier", nameof(userPrincipal));
            }

            // Delete all expired authorization codes
            await this.TokenRepository.DeleteAuthorizationCodes(DateTimeOffset.UtcNow);

            // Add scope claims
            if (scope != null)
            {
                userPrincipal.Identity.AddClaim(scope.Select(x => new SentinelClaim(ClaimType.Scope, x)).ToArray());
            }

            // Create and store authorization code for future use
            this.logger.DebugFormat("Creating authorization code for client '{0}', redirect uri '{1}' and user '{2}'", client, redirectUri, userPrincipal.Identity.Name);

            var createResult = await this.TokenProvider.CreateAuthorizationCode(
                client.Value,
                redirectUri,
                userPrincipal,
                scope,
                DateTimeOffset.UtcNow.Add(expire));

            // Add authorization code to database
            var insertResult = await this.TokenRepository.InsertAuthorizationCode(createResult.Entity);

            if (insertResult != null)
            {
                this.logger.Debug("Successfully created and stored authorization code");

                return(new TokenCreationResult <IAuthorizationCode>(createResult.Token, insertResult));
            }

            this.logger.Error("Unable to create and/or store authorization code");

            return(null);
        }