/// <summary>Gets the identity for the specified credentials.</summary>
        /// <param name="credentials">The credentials.</param>
        /// <returns>The identity.</returns>
        private async Task <ISentinelIdentity> GetIdentity(SignatureAuthenticationDigest credentials)
        {
            if (credentials.ClientId == credentials.UserId)
            {
                // Validate client using api key
                var client = await this.options.ClientManager.AuthenticateClientWithSignatureAsync(credentials);

                if (client.Identity.IsAuthenticated)
                {
                    return(client.Identity);
                }
            }

            try
            {
                // Validate user
                var user = await this.options.UserManager.AuthenticateUserWithSignatureAsync(credentials);

                if (user.Identity.IsAuthenticated)
                {
                    return(user.Identity);
                }
            }
            catch (ArgumentException ex)
            {
                this.options.Logger.Error(ex);
            }

            return(SentinelIdentity.Anonymous);
        }
        private bool ValidateDigest(SignatureAuthenticationDigest digest)
        {
            // 1. Validate timestamp is within boundaries
            var serverTimestamp = DateTimeOffset.UtcNow.ToUnixTime();

            if (digest.Timestamp > (serverTimestamp + this.options.MaximumClockSkew.TotalSeconds) ||
                digest.Timestamp < (serverTimestamp - this.options.MaximumClockSkew.TotalSeconds))
            {
                this.options.Logger.Warn("The request timestamp is outside the allowed boundaries");

                return(false);
            }

            // 2. Validate nonce has not been used before in the last 5 minutes
            if (this.nonces.Contains($"{digest.ClientId}_{digest.Nonce}"))
            {
                this.options.Logger.Warn("The nonce has been used recently");

                return(false);
            }
            else
            {
                this.nonces.Add($"{digest.ClientId}_{digest.Nonce}", digest, DateTimeOffset.UtcNow.Add(this.options.MaximumClockSkew));
            }

            // 3. TODO: Validate uri


            return(true);
        }
Exemplo n.º 3
0
        public async void AuthenticateClientWithApiKeyAsync_WhenGivenInvalidApiKeyAuthenticationDigest_ReturnsNotAuthenticatedIdentity(string username, string privateKey)
        {
            var digest    = new SignatureAuthenticationDigest(username, username, "http://localhost", "/openid/userinfo", DateTimeOffset.UtcNow.ToUnixTime(), Guid.NewGuid().ToString("N"));
            var signature = this.AsymmetricCryptoProvider.Sign(digest.GetData(), privateKey);

            digest.Sign(signature);

            var client = await this.ClientManager.AuthenticateClientWithSignatureAsync(digest);

            Assert.IsFalse(client.Identity.IsAuthenticated, "The client was authenticated");
        }
Exemplo n.º 4
0
        public async void GetResource_WhenGivenInvalidUserSignatureAuthentication_ReturnsData(string username, string privateKey)
        {
            var request = new HttpRequestMessage(HttpMethod.Get, "openid/userinfo");

            var digest    = new SignatureAuthenticationDigest(username, "NUnit", "http://localhost", request.RequestUri.ToString(), DateTimeOffset.UtcNow.ToUnixTime(), Guid.NewGuid().ToString("N"));
            var signature = this.AsymmetricCryptoProvider.Sign(digest.GetData(), privateKey);

            digest.Sign(signature);

            request.Headers.Authorization = new SignatureAuthenticationHeaderValue(digest);

            var response = await this.Client.SendAsync(request);

            Assert.AreEqual(response.StatusCode, HttpStatusCode.Unauthorized, "User was authenticated");
        }
Exemplo n.º 5
0
        public async void AuthenticateUserWithApiKeyAsync_WhenGivenInvalidApiKeyAuthenticationDigest_ReturnsNotAuthenticatedIdentity(string username, string password)
        {
            var digest = new SignatureAuthenticationDigest(
                username,
                password,
                "http://localhost",
                "http://localhost/url",
                DateTimeOffset.Now.ToUnixTime(),
                "aabbccddee");
            var signature = this.asymmetricCryptoProvider.Sign(digest.GetData(), password);

            digest.Sign(signature);

            var user = await this.UserManager.AuthenticateUserWithSignatureAsync(digest);

            Assert.IsFalse(user.Identity.IsAuthenticated, "The user was authenticated");
        }
Exemplo n.º 6
0
        public async void GetResource_WhenGivenValidUserSignatureAuthentication_ReturnsData(string username, string privateKey)
        {
            var request = new HttpRequestMessage(HttpMethod.Get, "openid/userinfo");

            var digest    = new SignatureAuthenticationDigest(username, "NUnit", "http://localhost", request.RequestUri.ToString(), DateTimeOffset.UtcNow.ToUnixTime(), Guid.NewGuid().ToString("N"));
            var signature = this.AsymmetricCryptoProvider.Sign(digest.GetData(), privateKey);

            digest.Sign(signature);

            request.Headers.Authorization = new SignatureAuthenticationHeaderValue(digest);

            var response = await this.Client.SendAsync(request);

            var userInfo = JsonConvert.DeserializeObject <IdentityResponse>(await response.Content.ReadAsStringAsync());

            Assert.IsTrue(response.IsSuccessStatusCode, "User was not authenticated");
            Assert.AreEqual(username, userInfo.Subject);
        }
        private async Task <bool> ValidateDigest(SignatureAuthenticationDigest digest)
        {
            // 1. Validate timestamp is within boundaries
            var serverTimestamp = DateTimeOffset.UtcNow.ToUnixTime();

            if (digest.Timestamp > (serverTimestamp + this.options.MaximumClockSkew.TotalSeconds) ||
                digest.Timestamp < (serverTimestamp - this.options.MaximumClockSkew.TotalSeconds))
            {
                this.options.Logger.Warn("The request timestamp is outside the allowed boundaries");

                return(false);
            }

            // 2. Validate nonce has not been used before in the last 5 minutes
            if (this.nonces.Contains($"{digest.ClientId}_{digest.Nonce}"))
            {
                this.options.Logger.Warn("The nonce has been used recently");

                return(false);
            }
            else
            {
                this.nonces.Add($"{digest.ClientId}_{digest.Nonce}", digest, DateTimeOffset.UtcNow.Add(this.options.MaximumClockSkew));
            }

            // 3. Validate client
            var client = await this.options.ClientManager.AuthenticateClientAsync(digest.ClientId, digest.RedirectUri);

            if (!client.Identity.IsAuthenticated)
            {
                return(false);
            }

            // 4. Validate url
            if (!this.Request.IsSameUrl(digest.RequestUrl))
            {
                this.options.Logger.Warn($"The request_url parameter ({digest.RequestUrl}) does not match the requested url {this.Request.Uri}");

                return(false);
            }

            return(true);
        }
Exemplo n.º 8
0
        /// <summary>Authenticate the user using an API key.</summary>
        /// <param name="digest">The digest.</param>
        /// <returns>The user principal.</returns>
        public override async Task <ISentinelPrincipal> AuthenticateUserWithSignatureAsync(SignatureAuthenticationDigest digest)
        {
            var userKeys = await this.UserApiKeyRepository.GetForUser(digest.UserId);

            var matchingKey = this.ValidateApiKey(userKeys, digest.GetData(), digest.Signature);

            if (matchingKey != null)
            {
                var user = await this.UserRepository.GetUser(matchingKey.UserId);

                if (user != null)
                {
                    var principal =
                        new SentinelPrincipal(
                            new SentinelIdentity(
                                AuthenticationType.Signature,
                                new SentinelClaim(JwtClaimType.Name, user.UserId),
                                new SentinelClaim(ClaimTypes.AuthenticationMethod, AuthenticationMethod.ApiKey),
                                new SentinelClaim(ClaimType.AuthenticationSource, "local"),
                                new SentinelClaim(JwtClaimType.GivenName, user.FirstName),
                                new SentinelClaim(JwtClaimType.FamilyName, user.LastName)));

                    user.LastLogin = DateTimeOffset.UtcNow;
                    await this.UserRepository.Update(user.GetIdentifier(), user);

                    matchingKey.LastUsed = DateTimeOffset.UtcNow;
                    await this.UserApiKeyRepository.Update(matchingKey.GetIdentifier(), matchingKey);

                    return(principal);
                }
            }

            return(SentinelPrincipal.Anonymous);
        }
Exemplo n.º 9
0
 public async Task <ISentinelPrincipal> AuthenticateUserWithSignatureAsync(SignatureAuthenticationDigest digest)
 {
     return(new SentinelPrincipal(new SentinelIdentity(AuthenticationType.Signature, new SentinelClaim(JwtClaimType.Name, digest.UserId))));
 }
 /// <summary>Authenticate the user using an API key.</summary>
 /// <param name="digest">The digest.</param>
 /// <returns>The user principal.</returns>
 public virtual async Task <ISentinelPrincipal> AuthenticateUserWithSignatureAsync(SignatureAuthenticationDigest digest)
 {
     throw new NotImplementedException();
 }
Exemplo n.º 11
0
        /// <summary>Authenticate client using API Key.</summary>
        /// <exception cref="ArgumentException">
        /// Thrown when one or more arguments have unsupported or illegal values.
        /// </exception>
        /// <param name="digest">The digest.</param>
        /// <returns>The client principal.</returns>
        public override async Task <ISentinelPrincipal> AuthenticateClientWithSignatureAsync(SignatureAuthenticationDigest digest)
        {
            // 1. Validate client id and redirect uri
            var client = await this.ClientRepository.GetClient(digest.ClientId);

            if (client == null || !client.Enabled)
            {
                throw new ArgumentException(nameof(digest), "The client_id is invalid");
            }

            if (client.RedirectUri != digest.RedirectUri)
            {
                throw new ArgumentException(nameof(digest), "The redirect_uri is invalid");
            }

            // 2. Validate username and signature using client secret
            if (digest.UserId != client.ClientId)
            {
                throw new ArgumentException(nameof(digest), "The user_id is invalid, must be equal to client_id");
            }

            if (!string.IsNullOrEmpty(client.PublicKey))
            {
                var isValid = this.AsymmetricCryptoProvider.ValidateSignature(digest.GetData(), digest.Signature, client.PublicKey);
                if (isValid)
                {
                    var principal =
                        new SentinelPrincipal(
                            new SentinelIdentity(
                                AuthenticationType.Signature,
                                new SentinelClaim(JwtClaimType.Name, client.ClientId),
                                new SentinelClaim(ClaimTypes.NameIdentifier, client.ClientId),
                                new SentinelClaim(ClaimType.Client, client.ClientId),
                                new SentinelClaim(ClaimType.RedirectUri, client.RedirectUri),
                                new SentinelClaim(ClaimTypes.AuthenticationMethod, AuthenticationMethod.Signature)));

                    if (principal.Identity.IsAuthenticated)
                    {
                        client.LastUsed = DateTimeOffset.UtcNow;
                        await this.ClientRepository.Update(client.GetIdentifier(), client);

                        return(principal);
                    }

                    return(principal);
                }
            }

            return(SentinelPrincipal.Anonymous);
        }
Exemplo n.º 12
0
 public SignatureAuthenticationHeaderValue(SignatureAuthenticationDigest digest)
     : base("Signature", EncodeString(digest.ToString()))
 {
 }
Exemplo n.º 13
0
 public Task <ISentinelPrincipal> AuthenticateClientWithSignatureAsync(SignatureAuthenticationDigest digest)
 {
     throw new System.NotImplementedException();
 }
Exemplo n.º 14
0
 /// <summary>Authenticate the user using an API key.</summary>
 /// <param name="digest">The digest.</param>
 /// <returns>The user principal.</returns>
 public abstract Task <ISentinelPrincipal> AuthenticateUserWithSignatureAsync(SignatureAuthenticationDigest digest);