public async Task <ActionResult <DeviceCode> > GetDeviceCodeByUserCodeAsync(string userCode)
        {
            // validate client
            var clientResult = await _clientValidator.ValidateAsync(this.HttpContext);

            if (clientResult.Client == null)
            {
                return(Unauthorized(OidcConstants.TokenErrors.InvalidClient));
            }

            var grantType = clientResult.Client.AllowedGrantTypes.FirstOrDefault(agt => agt == OidcConstants.GrantTypes.DeviceCode);

            if (grantType == null)
            {
                return(Unauthorized(OidcConstants.TokenErrors.InvalidGrant));
            }

            var deviceCode = await _deviceFlowStore.FindByUserCodeAsync(userCode.Sha256());

            if (deviceCode == null)
            {
                return(NotFound());
            }
            return(deviceCode);
        }
        private async Task <IEndpointResult> ProcessDeviceAuthorizationRequestAsync(HttpContext context)
        {
            _logger.LogDebug("Start device authorize request.");

            // validate client
            var clientResult = await _clientValidator.ValidateAsync(context);

            if (clientResult.Client == null)
            {
                return(Error(OidcConstants.TokenErrors.InvalidClient));
            }

            // validate request
            var form          = (await context.Request.ReadFormAsync()).AsNameValueCollection();
            var requestResult = await _requestValidator.ValidateAsync(form, clientResult);

            if (requestResult.IsError)
            {
                await _events.RaiseAsync(new DeviceAuthorizationFailureEvent(requestResult));

                return(Error(requestResult.Error, requestResult.ErrorDescription));
            }

            var baseUrl = context.GetIdentityServerBaseUrl().EnsureTrailingSlash();

            // create response
            _logger.LogTrace("Calling into device authorize response generator: {type}", _responseGenerator.GetType().FullName);
            var response = await _responseGenerator.ProcessAsync(requestResult, baseUrl);

            await _events.RaiseAsync(new DeviceAuthorizationSuccessEvent(response, requestResult));

            // return result
            _logger.LogDebug("Device authorize request success.");
            return(new DeviceAuthorizationResult(response));
        }
예제 #3
0
        public async Task ValidateAsync(ExtensionGrantValidationContext context)
        {
//            var audienceName = context.Request.Raw.Get("audience");
//            var audience = await _resourceStore.FindApiResourceAsync(audienceName);

            var userToken = context.Request.Raw.Get("subject_token");

            if (string.IsNullOrEmpty(userToken))
            {
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
                return;
            }

            var clientValidationResult = await _clientValidator.ValidateAsync(_context.HttpContext);

            var result = await _validator.ValidateAccessTokenAsync(userToken);

            if (result.IsError)
            {
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant);
                return;
            }
//          // get user's identity
            var sub = result.Claims.FirstOrDefault(c => c.Type == "sub")?.Value;

            context.Result = new GrantValidationResult(sub, GrantType, new []
            {
                new Claim("act",
                          JsonConvert.SerializeObject(new { sub = clientValidationResult.Client.ClientId }),
                          IdentityServerConstants.ClaimValueTypes.Json)
            });

            return;
        }
        private async Task <IEndpointResult> ProcessTokenRequestAsync(HttpContext context)
        {
            // validate client
            var clientResult = await _clientValidator.ValidateAsync(context);

            if (clientResult.Client == null)
            {
                return(Error(OidcConstants.TokenErrors.InvalidClient));
            }

            // validate request
            var form          = (await context.Request.ReadFormAsync()).AsNameValueCollection();
            var requestResult = await _requestValidator.ValidateRequestAsync(form, clientResult);

            if (requestResult.IsError)
            {
                await _events.RaiseAsync(new TokenIssuedFailureEvent(requestResult));

                return(Error(requestResult.Error, requestResult.ErrorDescription, requestResult.CustomResponse));
            }

            // create response
            var response = await _responseGenerator.ProcessAsync(requestResult);

            await _events.RaiseAsync(new TokenIssuedSuccessEvent(response, requestResult));

            // return result
            return(new TokenResult(response));
        }
        public async Task <ClientSecretValidationResult> ValidateAsync(HttpContext context)
        {
            _logger.LogDebug("Start InternalServiceClient Validation");

            var body = await context.Request.ReadFormAsync();

            if (body != null)
            {
                if (!validateClient(body))
                {
                    return(new ClientSecretValidationResult
                    {
                        Error = "invalid_client",
                        ErrorDescription = "This endpoint is only allowed for service clients"
                    });
                }
                else
                {
                    // Check if the client exists and enabled in the database
                    var clientResult = await _clientValidator.ValidateAsync(context);

                    // Whatever is the result error or success, pass it back
                    return(clientResult);
                }
            }
            _logger.LogDebug("Completed InternalServiceClient Validation");
            return(null);
        }
예제 #6
0
        public async Task ValidateAsync(ExtensionGrantValidationContext context)
        {
            _logger.LogDebug("Start token request validation");

            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            var raw = context.Request.Raw;
            var validatedRequest = new ValidatedTokenRequest
            {
                Raw = raw ?? throw new ArgumentNullException(nameof(raw)),
                            Options = _options
            };
            var customTokenRequestValidationContext = new CustomTokenRequestValidationContext()
            {
                Result = new TokenRequestValidationResult(validatedRequest)
            };
            await _arbitraryNoSubjectRequestValidator.ValidateAsync(customTokenRequestValidationContext);

            if (customTokenRequestValidationContext.Result.IsError)
            {
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest,
                                                           customTokenRequestValidationContext.Result.Error);
                return;
            }

            // validate HTTP for clients
            if (HttpMethods.IsPost(_httpContextAccessor.HttpContext.Request.Method) && _httpContextAccessor.HttpContext.Request.HasFormContentType)
            {
                // validate client
                var clientResult = await _clientValidator.ValidateAsync(_httpContextAccessor.HttpContext);

                if (!clientResult.IsError)
                {
                    validatedRequest.SetClient(clientResult.Client);
                }
            }

            /////////////////////////////////////////////
            // check grant type
            /////////////////////////////////////////////
            var grantType = validatedRequest.Raw.Get(OidcConstants.TokenRequest.GrantType);

            if (grantType.IsMissing())
            {
                LogError("Grant type is missing");
                context.Result = new GrantValidationResult(TokenRequestErrors.UnsupportedGrantType);
                return;
            }
            if (grantType.Length > _options.InputLengthRestrictions.GrantType)
            {
                LogError("Grant type is too long");
                context.Result = new GrantValidationResult(TokenRequestErrors.UnsupportedGrantType);
                return;
            }

            validatedRequest.GrantType = grantType;
            context.Result             = new GrantValidationResult();
        }
예제 #7
0
        private async Task <IdpTokenResponse> GetIdpToken(NameValueCollection parameters)
        {
            var clientResult = await _clientValidator.ValidateAsync(_httpContextAccessor.HttpContext);

            if (clientResult.IsError)
            {
                return(new IdpTokenResponse {
                    Custom = new Dictionary <string, object> {
                        { "Error", "invalid_client" }, { "ErrorDescription", "Invalid client/secret combination" }
                    }
                });
            }

            var validationResult = await _requestValidator.ValidateRequestAsync(parameters, clientResult);

            if (validationResult.IsError)
            {
                return(new IdpTokenResponse {
                    Custom = new Dictionary <string, object> {
                        { "Error", validationResult.Error }, { "ErrorDescription", validationResult.ErrorDescription }
                    }
                });
            }

            return(await _responseGenerator.ProcessAsync(validationResult));
        }
예제 #8
0
        public override async Task <IEndpointResult> ProcessAsync(HttpContext context)
        {
            Logger.LogDebug("Start authorize2 request");

            if (!HttpMethods.IsPost(context.Request.Method))
            {
                Logger.LogWarning("Invalid HTTP request for token endpoint");
                return(Error(Authorize2Constants.Authorize2Errors.InvalidRequest));
            }

            var tokenUsageResult = await _tokenUsageValidator.ValidateAsync(context);

            if (tokenUsageResult.TokenFound == false)
            {
                var error = "No access token found.";

                _logger.LogError(error);
                return(Error(OidcConstants.ProtectedResourceErrors.InvalidToken));
            }

            if (!context.Request.HasFormContentType)
            {
                return(new StatusCodeResult(HttpStatusCode.UnsupportedMediaType));
            }

            // validate the request
            Logger.LogTrace("Calling into userinfo request validator: {type}", _requestValidator.GetType().FullName);
            var validationResult = await _requestValidator.ValidateRequestAsync(tokenUsageResult.Token);

            if (validationResult.IsError)
            {
                //_logger.LogError("Error validating  validationResult.Error);
                return(Error(validationResult.Error));
            }


            // validate client
            var clientResult = await _clientValidator.ValidateAsync(context);

            if (clientResult.Client == null)
            {
                return(Error(Authorize2Constants.Authorize2Errors.InvalidClient));
            }

            // validate request
            NameValueCollection values = (await context.Request.ReadFormAsync()).AsNameValueCollection();

            Logger.LogTrace("Calling into token request validator: {type}", _validator2.GetType().FullName);
            var requestResult = await _validator2.ValidateRequestAsync(values, clientResult);

            // var user = await UserSession.GetUserAsync();
            var user   = validationResult.Subject;
            var result = await ProcessAuthorizeRequestAsync(values, user, null);

            Logger.LogTrace("End authorize request. result type: {0}", result?.GetType().ToString() ?? "-none-");

            //    return Error(Authorize2Constants.Authorize2Errors.InvalidClient);
            return(new Authorize2Result(result as AuthorizeResult));
        }
        public async Task Invoke(HttpContext httpContext, IScopedStorage scopedStorage)
        {
            if (!string.IsNullOrEmpty(PathRootUrl))
            {
                FixUpPath(httpContext);
            }

            // start tracking
            await FetchDiscoveryData(httpContext);

            var endpointKey = (from item in _endpointDictionary
                               where item.Value == httpContext.Request.Path.Value
                               select item.Key).FirstOrDefault();

            if (endpointKey == null)
            {
                // not for us
                await _next(httpContext);

                return;
            }

            _logger.LogInformation($"endpointKey={endpointKey},path={httpContext.Request.Path}");
            var requestRecord = new IdentityServerRequestRecord
            {
                HttpContext = httpContext,
                EndpointKey = endpointKey
            };

            // validate HTTP for clients
            if (HttpMethods.IsPost(httpContext.Request.Method) && httpContext.Request.HasFormContentType)
            {
                // validate client
                var clientResult = await _clientValidator.ValidateAsync(httpContext);

                if (!clientResult.IsError)
                {
                    requestRecord.Client = clientResult.Client;
                }
            }

            foreach (var evaluator in _evaluators)
            {
                var directive = await ProcessPreEvaluatorAsync(evaluator, requestRecord);

                if (directive == RequestTrackerEvaluatorDirective.DenyRequest)
                {
                    return; // do not continue to the real IdentityServer4 middleware.
                }
            }

            scopedStorage.Storage["IdentityServerRequestRecord"] = requestRecord;
            //
            // The following invoke is letting the request continue on into the pipeline
            //

            await _next(httpContext);
        }
        private async Task <IEndpointResult> ProcessTokenRequestAsync(HttpContext context)
        {
            _logger.LogDebug("Start token request.");
            // validate request
            var form     = (await context.Request.ReadFormAsync()).AsNameValueCollection();
            var userName = form.Get(OidcConstants.TokenRequest.UserName);
            var password = form.Get(OidcConstants.TokenRequest.Password);
            var scope    = form.Get(OidcConstants.TokenRequest.Scope);

            if (scope == "phone_number")
            {
                var getUserByPhoneNumber = await _usersService.GetByPhoneNumberOTP(userName, password);

                if (getUserByPhoneNumber != null)
                {
                    form.Remove("username");
                    form.Remove("password");
                    form.Remove("scope");
                    form.Add("username", getUserByPhoneNumber.Username);
                    form.Add("password", getUserByPhoneNumber.Password);
                    scope = null;
                    //form.Add("scope", "openid");
                }
            }
            // validate client
            var clientResult = await _clientValidator.ValidateAsync(context);

            if (clientResult.Client == null)
            {
                return(Error(OidcConstants.TokenErrors.InvalidClient));
            }

            // validate request
            //var form = (await context.Request.ReadFormAsync()).AsNameValueCollection();
            _logger.LogTrace("Calling into token request validator: {type}", _requestValidator.GetType().FullName);
            var requestResult = await _requestValidator.ValidateRequestAsync(form, clientResult);

            if (requestResult.IsError)
            {
                await _events.RaiseAsync(new TokenIssuedFailureEvent(requestResult));

                return(Error(requestResult.Error, requestResult.ErrorDescription, requestResult.CustomResponse));
            }

            // create response
            _logger.LogTrace("Calling into token request response generator: {type}", _responseGenerator.GetType().FullName);
            var response = await _responseGenerator.ProcessAsync(requestResult);

            await _events.RaiseAsync(new TokenIssuedSuccessEvent(response, requestResult));

            LogTokens(response, requestResult);

            // return result
            _logger.LogDebug("Token request success.");
            return(new TokenResult(response));
        }
예제 #11
0
        private async Task <IEndpointResult> ProcessTokenRequestAsync(HttpContext context)
        {
            _logger.LogTrace("Start token request.");

            // validate client
            var clientResult = await _clientValidator.ValidateAsync(context);

            if (clientResult.Client == null)
            {
                _logger.LogDebug("Invalid client");
                return(Error(OidcConstants.TokenErrors.InvalidClient));
            }

            // validate request
            var form = (await context.Request.ReadFormAsync()).AsNameValueCollection();

            if (_logger.IsEnabled(LogLevel.Trace))
            {
                _logger.LogTrace("Calling into token request validator: {type}", _requestValidator.GetType().FullName);
            }

            var requestResult = await _requestValidator.ValidateRequestAsync(form, clientResult);

            if (requestResult.IsError)
            {
                _logger.LogDebug("Token issued failure");
                await _events.RaiseAsync(new TokenIssuedFailureEvent(requestResult));

                return(Error(requestResult.Error, requestResult.ErrorDescription, requestResult.CustomResponse));
            }

            _logger.LogDebug("Get IP address and device type");
            requestResult.ValidatedRequest.ClientIp = context.GetRequestIp();
            requestResult.ValidatedRequest.Device   = context
                                                      .GetHeaderValueAs <string>("User-Agent")
                                                      .GetDevice();

            // create response
            if (_logger.IsEnabled(LogLevel.Trace))
            {
                _logger.LogTrace("Calling into token request response generator: {type}", _responseGenerator.GetType().FullName);
            }

            var response = await _responseGenerator.ProcessAsync(requestResult);

            _logger.LogTrace("Raise token issued successfully event");
            await _events.RaiseAsync(new TokenIssuedSuccessEvent(response, requestResult));

            LogTokens(response, requestResult);

            // return result
            _logger.LogDebug("Token request success.");
            return(new TokenResult(response));
        }
예제 #12
0
        private async Task <IEndpointResult> ProcessRevocationRequestAsync(HttpContext context)
        {
            _logger.LogDebug("Start revocation request.");

            // validate client
            var clientValidationResult = await _clientValidator.ValidateAsync(context);

            if (clientValidationResult.IsError)
            {
                return(new TokenRevocationErrorResult(OidcConstants.TokenErrors.InvalidClient));
            }

            _logger.LogTrace("Client validation successful");

            // validate the token request
            var form = (await context.Request.ReadFormAsync()).AsNameValueCollection();

            _logger.LogTrace("Calling into token revocation request validator: {type}", _requestValidator.GetType().FullName);
            var requestValidationResult = await _requestValidator.ValidateRequestAsync(form, clientValidationResult.Client);

            if (requestValidationResult.IsError)
            {
                return(new TokenRevocationErrorResult(requestValidationResult.Error));
            }

            _logger.LogTrace("Calling into token revocation response generator: {type}", _responseGenerator.GetType().FullName);
            var response = await _responseGenerator.ProcessAsync(requestValidationResult);

            if (response.Success)
            {
                _logger.LogInformation("Token revocation complete");
                await _events.RaiseAsync(new TokenRevokedSuccessEvent(requestValidationResult, requestValidationResult.Client));
            }
            else
            {
                _logger.LogInformation("No matching token found");
            }

            if (response.Error.IsPresent())
            {
                return(new TokenRevocationErrorResult(response.Error));
            }

            return(new StatusCodeResult(HttpStatusCode.OK));
        }
        public async Task ValidateAsync(ExtensionGrantValidationContext context)
        {
            _logger.LogDebug("Start token request validation");


            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            var raw = context.Request.Raw;

            _validatedRequest = new ValidatedTokenRequest
            {
                Raw = raw ?? throw new ArgumentNullException(nameof(raw)),
                            Options = _options
            };
            var customTokenRequestValidationContext = new CustomTokenRequestValidationContext()
            {
                Result = new TokenRequestValidationResult(_validatedRequest)
            };
            await _arbitraryNoSubjectRequestValidator.ValidateAsync(customTokenRequestValidationContext);

            if (customTokenRequestValidationContext.Result.IsError)
            {
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest,
                                                           customTokenRequestValidationContext.Result.Error);
                return;
            }
            var clientResult = await _clientValidator.ValidateAsync(_httpContextAccessor.HttpContext);

            if (!clientResult.IsError)
            {
                _validatedRequest.SetClient(clientResult.Client);
            }


            /////////////////////////////////////////////
            // check grant type
            /////////////////////////////////////////////
            var grantType = _validatedRequest.Raw.Get(OidcConstants.TokenRequest.GrantType);

            _validatedRequest.GrantType = grantType;
            context.Result = new GrantValidationResult();
        }
            public async Task ExecuteAsync(HttpContext context)
            {
                _logger.LogDebug("Constructing token result");

                var issuer = context.GetIdentityServerIssuerUri();

                var audience = _session.RequestParameters.ContainsKey(IdentityConstants.ClientId) ? _session.RequestParameters[IdentityConstants.ClientId] : "";

                _logger.LogDebug($"Generating token for audience : {audience}");

                var token = await _tokenIssuerService.IssueJwtAsync(10000, issuer, new string[] { audience }, await GetClaims());

                _logger.LogDebug($"Token created, invalidating session");

                if (_sessionStorage.DeleteSession(_session) == false)
                {
                    _logger.LogError("Failed to delete a session");
                }

                _logger.LogDebug($"Returning token result");

                var clientResult = await _clientValidator.ValidateAsync(context);

                if (clientResult.Client.AllowedCorsOrigins.Count() == 1)
                {
                    _logger.LogDebug("Adding Access-Control-Allow-Origin header");
                    context.Response.Headers.Add("Access-Control-Allow-Origin", clientResult.Client.AllowedCorsOrigins.ToArray());
                }
                else
                {
                    _logger.LogError("Multiple Access-Control-Allow-Origin headers defined");
                }

                await context.Response.WriteJsonAsync(new
                {
                    access_token = "invalid",
                    id_token     = token,
                    token_type   = "Bearer"
                });
            }
예제 #15
0
        private async Task <IEndpointResult> ProcessTokenRequestAsync(HttpContext context)
        {
            _logger.LogDebug("Start token request.");

            // validate client
            var clientResult = await _clientValidator.ValidateAsync(context);

            if (clientResult.Client == null)
            {
                return(Error(OidcConstants.TokenErrors.InvalidClient));
            }

            // validate request
            var form = (await context.Request.ReadFormAsync()).AsNameValueCollection();

            _logger.LogTrace("Calling into token request validator: {type}", _requestValidator.GetType().FullName);
            var requestResult = await _requestValidator.ValidateRequestAsync(form, clientResult);

            if (requestResult.IsError)
            {
                await _events.RaiseAsync(new TokenIssuedFailureEvent(requestResult));

                return(Error(requestResult.Error, requestResult.ErrorDescription, requestResult.CustomResponse));
            }

            // create response
            _logger.LogTrace("Calling into token request response generator: {type}", _responseGenerator.GetType().FullName);
            var response = await _responseGenerator.ProcessAsync(requestResult);

            await _events.RaiseAsync(new TokenIssuedSuccessEvent(response, requestResult));

            LogTokens(response, requestResult);

            // return result
            _logger.LogDebug("Token request success.");
            return(new TokenResult(response));
        }
        public async Task ValidateAsync(ExtensionGrantValidationContext context)
        {
            _logger.LogDebug("Start token request validation");


            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            var raw = context.Request.Raw;

            _validatedRequest = new ValidatedTokenRequest
            {
                Raw = raw ?? throw new ArgumentNullException(nameof(raw)),
                            Options = _options
            };
            var customTokenRequestValidationContext = new CustomTokenRequestValidationContext()
            {
                Result = new TokenRequestValidationResult(_validatedRequest)
            };
            await _arbitraryResourceOwnerRequestValidator.ValidateAsync(customTokenRequestValidationContext);

            if (customTokenRequestValidationContext.Result.IsError)
            {
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest,
                                                           customTokenRequestValidationContext.Result.Error);
                return;
            }


            var clientResult = await _clientValidator.ValidateAsync(_httpContextAccessor.HttpContext);

            if (!clientResult.IsError)
            {
                _validatedRequest.SetClient(clientResult.Client);
            }

            /////////////////////////////////////////////
            // get the grant type
            // NOTE: The identityserver4 pipeline before us validated to obvious stuff
            /////////////////////////////////////////////
            var grantType = _validatedRequest.Raw.Get(OidcConstants.TokenRequest.GrantType);

            _validatedRequest.GrantType = grantType;

            var subject = "";

            if (string.IsNullOrWhiteSpace(subject))
            {
                subject = context.Request.Raw.Get("subject");
            }

            // get user's identity
            var claims = new List <Claim>
            {
                new Claim(ClaimTypes.NameIdentifier, subject),
                new Claim("sub", subject)
            };

            var principal = new ClaimsPrincipal(new ClaimsIdentity(claims));

            _principalAugmenter.AugmentPrincipal(principal);

            // optional stuff;
            var accessTokenLifetimeOverride = _validatedRequest.Raw.Get(Constants.AccessTokenLifetime);

            if (!string.IsNullOrWhiteSpace(accessTokenLifetimeOverride))
            {
                int  accessTokenLifetime = 0;
                bool error = true;
                if (Int32.TryParse(accessTokenLifetimeOverride, out accessTokenLifetime))
                {
                    if (accessTokenLifetime > 0 && accessTokenLifetime <= context.Request.AccessTokenLifetime)
                    {
                        context.Request.AccessTokenLifetime = accessTokenLifetime;
                        error = false;
                    }
                }
                if (error)
                {
                    var errorDescription =
                        $"{Constants.AccessTokenLifetime} out of range.   Must be > 0 and <= configured AccessTokenLifetime.";
                    LogError(errorDescription);
                    context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest, errorDescription);
                    return;
                }
            }

            context.Result = new GrantValidationResult(principal.GetSubjectId(),
                                                       ArbitraryResourceOwnerExtensionGrant.Constants.ArbitraryResourceOwner);
        }
        public async Task ValidateAsync(ExtensionGrantValidationContext context)
        {
            _logger.LogDebug("Start token request validation");

            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            var contextClient = (context.Request.Client as ClientExtra).ShallowCopy();

            context.Request.Client = contextClient;
            var raw = context.Request.Raw;

            _validatedRequest = new ValidatedTokenRequest
            {
                Raw = raw ?? throw new ArgumentNullException(nameof(raw)),
                            Options = _options
            };
            var customTokenRequestValidationContext = new CustomTokenRequestValidationContext()
            {
                Result = new TokenRequestValidationResult(_validatedRequest)
            };
            await _arbitraryIdentityRequestValidator.ValidateAsync(customTokenRequestValidationContext);

            if (customTokenRequestValidationContext.Result.IsError)
            {
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest,
                                                           customTokenRequestValidationContext.Result.Error);
                return;
            }
            // validate HTTP for clients
            if (HttpMethods.IsPost(_httpContextAccessor.HttpContext.Request.Method) && _httpContextAccessor.HttpContext.Request.HasFormContentType)
            {
                // validate client
                var clientResult = await _clientValidator.ValidateAsync(_httpContextAccessor.HttpContext);

                if (!clientResult.IsError)
                {
                    _validatedRequest.SetClient(clientResult.Client);
                }
            }

            /////////////////////////////////////////////
            // check grant type
            /////////////////////////////////////////////
            var grantType = _validatedRequest.Raw.Get(OidcConstants.TokenRequest.GrantType);

            if (grantType.IsMissing())
            {
                LogError("Grant type is missing");
                context.Result = new GrantValidationResult(TokenRequestErrors.UnsupportedGrantType);
                return;
            }
            if (grantType.Length > _options.InputLengthRestrictions.GrantType)
            {
                LogError("Grant type is too long");
                context.Result = new GrantValidationResult(TokenRequestErrors.UnsupportedGrantType);
                return;
            }

            _validatedRequest.GrantType = grantType;
            var resource = await _resourceStore.GetAllResourcesAsync();

            var   subject             = "";
            Claim originAuthTimeClaim = null;
            // if access_token exists, it wins.
            var accessToken = context.Request.Raw.Get("access_token");

            if (!string.IsNullOrWhiteSpace(accessToken))
            {
                var validateAccessToken = await _tokenValidator.ValidateAccessTokenAsync(accessToken);

                var queryClaims = from item in validateAccessToken.Claims
                                  where item.Type == JwtClaimTypes.Subject
                                  select item.Value;
                subject = queryClaims.FirstOrDefault();

                originAuthTimeClaim = (from item in validateAccessToken.Claims
                                       where item.Type == $"origin_{JwtClaimTypes.AuthenticationTime}"
                                       select item).FirstOrDefault();
                if (originAuthTimeClaim == null)
                {
                    var authTimeClaim = (from item in validateAccessToken.Claims
                                         where item.Type == JwtClaimTypes.AuthenticationTime
                                         select item).FirstOrDefault();
                    originAuthTimeClaim = new
                                          Claim($"origin_{JwtClaimTypes.AuthenticationTime}",
                                                authTimeClaim.Value);
                }
            }

            if (string.IsNullOrWhiteSpace(subject))
            {
                subject = context.Request.Raw.Get("subject");
            }
            // get user's identity
            var claims = new List <Claim>
            {
                new Claim(ClaimTypes.NameIdentifier, subject),
                new Claim("sub", subject)
            };

            var principal = new ClaimsPrincipal(new ClaimsIdentity(claims));

            _principalAugmenter.AugmentPrincipal(principal);
            var userClaimsFinal = new List <Claim>();


            // optional stuff;
            var accessTokenLifetimeOverride = _validatedRequest.Raw.Get(Constants.AccessTokenLifetime);

            if (!string.IsNullOrWhiteSpace(accessTokenLifetimeOverride))
            {
                var accessTokenLifetime = Int32.Parse(accessTokenLifetimeOverride);
                if (accessTokenLifetime > 0 && accessTokenLifetime <= context.Request.AccessTokenLifetime)
                {
                    context.Request.AccessTokenLifetime = accessTokenLifetime;
                }
                else
                {
                    var errorDescription =
                        $"{Constants.AccessTokenLifetime} out of range.   Must be > 0 and <= configured AccessTokenLifetime.";
                    LogError(errorDescription);
                    context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest, errorDescription);
                    return;
                }
            }
            // optional stuff;
            var idTokenLifetimeOverride = _validatedRequest.Raw.Get(Constants.IdTokenLifetime);

            if (!string.IsNullOrWhiteSpace(idTokenLifetimeOverride))
            {
                var idTokenLifetime = Int32.Parse(idTokenLifetimeOverride);
                if (idTokenLifetime > 0 && idTokenLifetime <= context.Request.Client.IdentityTokenLifetime)
                {
                    context.Request.Client.IdentityTokenLifetime = idTokenLifetime;
                }
                else
                {
                    var errorDescription =
                        $"{Constants.IdTokenLifetime} out of range.   Must be > 0 and <= configured IdentityTokenLifetime.";
                    LogError(errorDescription);
                    context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest, errorDescription);
                    return;
                }
            }
            //userClaimsFinal.Add(new Claim(ProfileServiceManager.Constants.ClaimKey, Constants.ArbitraryIdentityProfileService));
            if (originAuthTimeClaim != null)
            {
                userClaimsFinal.Add(originAuthTimeClaim);
            }
            context.Result = new GrantValidationResult(principal.GetSubjectId(), ArbitraryIdentityExtensionGrant.Constants.ArbitraryIdentity, userClaimsFinal);
        }
예제 #18
0
        public async Task <IEndpointResult> ProcessAsync(HttpContext context)
        {
            _logger.LogDebug("Processing Authorize request");

            NameValueCollection values;

            switch (context.Request.Method)
            {
            case "GET":
                values = context.Request.Query.AsNameValueCollection();
                break;

            case "POST":
                if (!context.Request.HasFormContentType)
                {
                    return(new StatusCodeResult(HttpStatusCode.UnsupportedMediaType));
                }
                values = context.Request.Form.AsNameValueCollection();
                break;

            default:
                return(new StatusCodeResult(HttpStatusCode.MethodNotAllowed));
            }

            var clientResult = await _clientValidator.ValidateAsync(context);

            if (clientResult.Client == null)
            {
                return(VCResponseHelpers.Error(OidcConstants.TokenErrors.InvalidClient));
            }

            var scopes = values.Get(IdentityConstants.ScopeParamName).Split(' ');

            if (!scopes.Contains(IdentityConstants.VCAuthnScopeName))
            {
                return(VCResponseHelpers.Error(IdentityConstants.MissingVCAuthnScopeError, IdentityConstants.MissingVCAuthnScopeDesc));
            }

            var presentationRecordId = values.Get(IdentityConstants.PresentationRequestConfigIDParamName);

            if (string.IsNullOrEmpty(presentationRecordId))
            {
                return(VCResponseHelpers.Error(IdentityConstants.InvalidPresentationRequestConfigIDError, IdentityConstants.InvalidPresentationRequestConfigIDDesc));
            }

            var redirectUrl = values.Get(IdentityConstants.RedirectUriParameterName);

            if (string.IsNullOrEmpty(redirectUrl))
            {
                return(VCResponseHelpers.Error(IdentityConstants.InvalidRedirectUriError));
            }

            if (clientResult.Client.RedirectUris.Any() && !clientResult.Client.RedirectUris.Contains(redirectUrl))
            {
                return(VCResponseHelpers.Error(IdentityConstants.InvalidRedirectUriError));
            }

            var responseType = values.Get(IdentityConstants.ResponseTypeUriParameterName);

            if (string.IsNullOrEmpty(responseType))
            {
                responseType = IdentityConstants.DefaultResponseType;
            }

            var responseMode = values.Get(IdentityConstants.ResponseModeUriParameterName);

            if (string.IsNullOrEmpty(responseMode))
            {
                responseMode = IdentityConstants.DefaultResponseMode;
            }

            PresentationConfiguration presentationRecord = await _presentationConfigurationService.GetAsync(presentationRecordId);

            if (presentationRecord == null)
            {
                return(VCResponseHelpers.Error(IdentityConstants.UnknownPresentationRecordId, "Cannot find respective record id"));
            }

            WalletPublicDid acapyPublicDid;

            try
            {
                acapyPublicDid = await _acapyClient.WalletDidPublic();
            }
            catch (Exception e)
            {
                _logger.LogError(e, "Cannot fetch ACAPy wallet public did");
                return(VCResponseHelpers.Error(IdentityConstants.AcapyCallFailed, "Cannot fetch ACAPy wallet public did"));
            }

            PresentationRequestMessage presentationRequest;
            string presentationRequestId;

            try
            {
                var response = await _acapyClient.CreatePresentationRequestAsync(presentationRecord.Configuration);

                presentationRequest   = BuildPresentationRequest(response, acapyPublicDid);
                presentationRequestId = response.PresentationExchangeId;
            }
            catch (Exception e)
            {
                _logger.LogError(e, "Failed to create presentation request");
                return(VCResponseHelpers.Error(IdentityConstants.AcapyCallFailed, "Failed to create presentation request"));
            }


            // create a full and short url versions of a presentation requests
            string shortUrl;

            try
            {
                var url = string.Format("{0}?m={1}", _options.PublicOrigin, presentationRequest.ToJson().ToBase64());
                shortUrl = await _urlShortenerService.CreateShortUrlAsync(url);
            }
            catch (Exception e)
            {
                _logger.LogError(e, "Presentation url build failed");
                return(VCResponseHelpers.Error(IdentityConstants.PresentationUrlBuildFailed, "Presentation url build failed"));
            }

            // persist presentation request details in session
            try
            {
                var session = await _sessionStorage.CreateSessionAsync(new AuthSession()
                {
                    PresentationRequestId = presentationRequestId,
                    PresentationRecordId  = presentationRecordId,
                    PresentationRequest   = presentationRequest.Request.ExtractIndyPresentationRequest().ToJson(),
                    RequestParameters     = values.AllKeys.ToDictionary(t => t, t => values[t])
                });

                // set up a session cookie
                context.Response.Cookies.Append(IdentityConstants.SessionIdCookieName, session.Id);
            }
            catch (Exception e)
            {
                _logger.LogError(e, "Failed to start a new session");
                return(VCResponseHelpers.Error(IdentityConstants.SessionStartFailed, "Failed to start a new session"));
            }

            return(new AuthorizationEndpointResult(
                       new AuthorizationViewModel(
                           shortUrl,
                           $"{_options.PublicOrigin}/{IdentityConstants.ChallengePollUri}?{IdentityConstants.ChallengeIdQueryParameterName}={presentationRequestId}",
                           $"{_options.PublicOrigin}/{IdentityConstants.AuthorizeCallbackUri}?{IdentityConstants.ChallengeIdQueryParameterName}={presentationRequestId}",
                           presentationRequest.ToJson()
                           )));
        }
예제 #19
0
        public async Task ValidateAsync(ExtensionGrantValidationContext context)
        {
            _logger.LogDebug("Start token request validation");

            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }
            var contextClient = (context.Request.Client as ClientExtra).ShallowCopy();

            context.Request.Client = contextClient;
            var raw = context.Request.Raw;

            _validatedRequest = new ValidatedTokenRequest
            {
                Raw = raw ?? throw new ArgumentNullException(nameof(raw)),
                            Options = _options
            };
            var customTokenRequestValidationContext = new CustomTokenRequestValidationContext()
            {
                Result = new TokenRequestValidationResult(_validatedRequest)
            };
            await _arbitraryIdentityRequestValidator.ValidateAsync(customTokenRequestValidationContext);

            if (customTokenRequestValidationContext.Result.IsError)
            {
                context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest,
                                                           customTokenRequestValidationContext.Result.Error);
                return;
            }
            // validate HTTP for clients
            if (HttpMethods.IsPost(_httpContextAccessor.HttpContext.Request.Method) && _httpContextAccessor.HttpContext.Request.HasFormContentType)
            {
                // validate client
                var clientResult = await _clientValidator.ValidateAsync(_httpContextAccessor.HttpContext);

                if (!clientResult.IsError)
                {
                    _validatedRequest.SetClient(clientResult.Client);
                }
            }

            /////////////////////////////////////////////
            // check grant type
            /////////////////////////////////////////////
            var grantType = _validatedRequest.Raw.Get(OidcConstants.TokenRequest.GrantType);


            _validatedRequest.GrantType = grantType;
            var resource = await _resourceStore.GetAllResourcesAsync();

            var subject = "";


            if (string.IsNullOrWhiteSpace(subject))
            {
                subject = context.Request.Raw.Get("subject");
            }
            // get user's identity
            var claims = new List <Claim>
            {
                new Claim(ClaimTypes.NameIdentifier, subject),
                new Claim("sub", subject),
                new Claim(JwtClaimTypes.IdentityProvider, _arbitraryIdentityExtensionGrantOptions.IdentityProvider)
            };

            var principal = new ClaimsPrincipal(new ClaimsIdentity(claims));

            _principalAugmenter.AugmentPrincipal(principal);
            var userClaimsFinal = new List <Claim>();


            // optional stuff;
            var accessTokenLifetimeOverride = _validatedRequest.Raw.Get(Constants.AccessTokenLifetime);

            if (!string.IsNullOrWhiteSpace(accessTokenLifetimeOverride))
            {
                int  accessTokenLifetime = 0;
                bool error = true;
                if (Int32.TryParse(accessTokenLifetimeOverride, out accessTokenLifetime))
                {
                    if (accessTokenLifetime > 0 && accessTokenLifetime <= context.Request.AccessTokenLifetime)
                    {
                        context.Request.AccessTokenLifetime = accessTokenLifetime;
                        error = false;
                    }
                }

                if (error)
                {
                    var errorDescription =
                        $"{Constants.AccessTokenLifetime} out of range.   Must be > 0 and <= configured AccessTokenLifetime.";
                    LogError(errorDescription);
                    context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest, errorDescription);
                    return;
                }
            }
            // optional stuff;
            var idTokenLifetimeOverride = _validatedRequest.Raw.Get(Constants.IdTokenLifetime);

            if (!string.IsNullOrWhiteSpace(idTokenLifetimeOverride))
            {
                int  idTokenLifetime = 0;
                bool error           = true;
                if (Int32.TryParse(idTokenLifetimeOverride, out idTokenLifetime))
                {
                    if (idTokenLifetime > 0 && idTokenLifetime <= context.Request.Client.IdentityTokenLifetime)
                    {
                        context.Request.Client.IdentityTokenLifetime = idTokenLifetime;
                        error = false;
                    }
                }

                if (error)
                {
                    var errorDescription =
                        $"{Constants.IdTokenLifetime} out of range.   Must be > 0 and <= configured IdentityTokenLifetime.";
                    LogError(errorDescription);
                    context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest, errorDescription);
                    return;
                }
            }

            context.Result = new GrantValidationResult(
                principal.GetSubjectId(),
                ArbitraryIdentityExtensionGrant.Constants.ArbitraryIdentity,
                userClaimsFinal,
                _arbitraryIdentityExtensionGrantOptions.IdentityProvider);
        }
예제 #20
0
        public async Task ValidateAsync(ExtensionGrantValidationContext context)
        {
            _logger.LogDebug("Start token request validation");

            string grantType = null;
            string clientId  = "";

            try
            {
                if (context == null)
                {
                    throw new ArgumentNullException(nameof(context));
                }
                var raw = context.Request.Raw;
                var validatedRequest = new ValidatedTokenRequest
                {
                    Raw = raw ?? throw new ArgumentNullException(nameof(raw)),
                                Options = _options
                };
                // validate HTTP for clients
                if (HttpMethods.IsPost(_httpContextAccessor.HttpContext.Request.Method) && _httpContextAccessor.HttpContext.Request.HasFormContentType)
                {
                    // validate client
                    var clientResult = await _clientValidator.ValidateAsync(_httpContextAccessor.HttpContext);

                    if (!clientResult.IsError)
                    {
                        validatedRequest.SetClient(clientResult.Client);
                        clientId = clientResult.Client.ClientId;
                    }
                }
                /////////////////////////////////////////////
                // get grant type.  This has already been validated by the time it gets here.
                /////////////////////////////////////////////
                grantType = validatedRequest.Raw.Get(OidcConstants.TokenRequest.GrantType);
                validatedRequest.GrantType = grantType;

                var customTokenRequestValidationContext = new CustomTokenRequestValidationContext()
                {
                    Result = new TokenRequestValidationResult(validatedRequest)
                };
                await _arbitraryResourceOwnerRequestValidator.ValidateAsync(customTokenRequestValidationContext);

                if (customTokenRequestValidationContext.Result.IsError)
                {
                    context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest,
                                                               customTokenRequestValidationContext.Result.Error);
                    throw new Exception("Invalid Request");
                }

                var subject = "";
                if (string.IsNullOrWhiteSpace(subject))
                {
                    subject = context.Request.Raw.Get("subject");
                }

                // get user's identity
                var claims = new List <Claim>
                {
                    new Claim(ClaimTypes.NameIdentifier, subject),
                    new Claim("sub", subject)
                };

                var principal = new ClaimsPrincipal(new ClaimsIdentity(claims));
                _principalAugmenter.AugmentPrincipal(principal);

                // optional stuff;
                var accessTokenLifetimeOverride = validatedRequest.Raw.Get(Constants.AccessTokenLifetime);
                if (!string.IsNullOrWhiteSpace(accessTokenLifetimeOverride))
                {
                    var accessTokenLifetime = Int32.Parse(accessTokenLifetimeOverride);
                    if (accessTokenLifetime > 0 && accessTokenLifetime <= context.Request.AccessTokenLifetime)
                    {
                        context.Request.AccessTokenLifetime = accessTokenLifetime;
                    }
                    else
                    {
                        var errorDescription =
                            $"{Constants.AccessTokenLifetime} out of range.   Must be > 0 and <= configured AccessTokenLifetime.";
                        LogError(errorDescription);
                        context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest, errorDescription);
                        throw new Exception(errorDescription);
                    }
                }

                context.Result = new GrantValidationResult(principal.GetSubjectId(),
                                                           ArbitraryResourceOwnerExtensionGrant.Constants.ArbitraryResourceOwner);
            }
            catch (Exception e)
            {
            }

            if (context.Result.IsError)
            {
                await _events.RaiseAsync(new ExtensionGrantValidationFailureEvent(
                                             clientId,
                                             grantType,
                                             context.Result.Error));
            }
        }
예제 #21
0
        public async Task <IEndpointResult> ProcessAsync(HttpContext context)
        {
            _logger.LogDebug($"Starting token request");

            NameValueCollection values;

            if (HttpMethods.IsPost(context.Request.Method))
            {
                if (!context.Request.HasFormContentType)
                {
                    _logger.LogDebug($"Unsupported media type");
                    return(new StatusCodeResult(HttpStatusCode.UnsupportedMediaType));
                }

                values = context.Request.Form.AsNameValueCollection();
            }
            else
            {
                _logger.LogDebug($"Method not allowed");
                return(new StatusCodeResult(HttpStatusCode.MethodNotAllowed));
            }

            var clientResult = await _clientValidator.ValidateAsync(context);

            if (clientResult.Client == null)
            {
                _logger.LogDebug($"Invalid client");
                return(VCResponseHelpers.Error(OidcConstants.TokenErrors.InvalidClient));
            }

            var grantType = values.Get(IdentityConstants.GrantTypeParameterName);

            if (string.IsNullOrEmpty(grantType))
            {
                _logger.LogDebug($"Invalid grant type of : {grantType}");
                return(VCResponseHelpers.Error(IdentityConstants.InvalidGrantTypeError));
            }

            var sessionId = values.Get(IdentityConstants.AuthorizationCodeParameterName);

            if (string.IsNullOrEmpty(sessionId))
            {
                _logger.LogDebug($"Invalid authorization code : {sessionId}");
                return(VCResponseHelpers.Error(IdentityConstants.InvalidAuthorizationCodeError));
            }

            var session = await _sessionStore.FindBySessionIdAsync(sessionId);

            if (session == null)
            {
                _logger.LogDebug($"Invalid session : {sessionId}");
                return(VCResponseHelpers.Error(IdentityConstants.InvalidSessionError, $"Cannot find stored session"));
            }

            if (session.PresentationRequestSatisfied == false)
            {
                _logger.LogDebug($"Presentation not satisfied, session id : {sessionId}");
                return(VCResponseHelpers.Error(IdentityConstants.InvalidSessionError, "Presentation request wasn't satisfied"));
            }

            try
            {
                _logger.LogDebug($"Constructing token result for session : {sessionId}");
                return(new TokenEndpointResult(session, _clientValidator, _tokenIssuerService, _presentationConfigurationService, _sessionStore, _logger));
            }
            catch (Exception e)
            {
                _logger.LogError(e, "Failed to create a token response");
                return(VCResponseHelpers.Error(IdentityConstants.GeneralError, "Failed to create a token"));
            }
        }