private async Task <TokenRequestValidationResult> ValidateDeviceCodeRequestAsync(NameValueCollection parameters)
        {
            _logger.LogDebug("Start validation of device code request");

            /////////////////////////////////////////////
            // check if client is authorized for grant type
            /////////////////////////////////////////////
            if (!_validatedRequest.Client.AllowedGrantTypes.ToList().Contains(GrantType.DeviceFlow))
            {
                LogError("Client not authorized for device flow");
                return(Invalid(OidcConstants.TokenErrors.UnauthorizedClient));
            }

            /////////////////////////////////////////////
            // validate device code parameter
            /////////////////////////////////////////////
            var deviceCode = parameters.Get(OidcConstants.TokenRequest.DeviceCode);

            if (deviceCode.IsMissing())
            {
                LogError("Device code is missing");
                return(Invalid(OidcConstants.TokenErrors.InvalidRequest));
            }

            if (deviceCode.Length > _options.InputLengthRestrictions.DeviceCode)
            {
                LogError("Device code too long");
                return(Invalid(OidcConstants.TokenErrors.InvalidGrant));
            }

            /////////////////////////////////////////////
            // validate device code
            /////////////////////////////////////////////
            var deviceCodeContext = new DeviceCodeValidationContext {
                DeviceCode = deviceCode, Request = _validatedRequest
            };
            await _deviceCodeValidator.ValidateAsync(deviceCodeContext);

            if (deviceCodeContext.Result.IsError)
            {
                return(deviceCodeContext.Result);
            }

            _logger.LogDebug("Validation of authorization code token request success");

            return(Valid());
        }
Exemple #2
0
        /// <summary>
        /// Validates the device code.
        /// </summary>
        /// <param name="context">The context.</param>
        /// <returns></returns>
        public async Task ValidateAsync(DeviceCodeValidationContext context)
        {
            var deviceCode = await _devices.FindByDeviceCodeAsync(context.DeviceCode);

            if (deviceCode == null)
            {
                _logger.LogError("Invalid device code");
                context.Result = new TokenRequestValidationResult(context.Request, OidcConstants.TokenErrors.InvalidGrant);
                return;
            }

            // validate client binding
            if (deviceCode.ClientId != context.Request.Client.ClientId)
            {
                _logger.LogError("Client {0} is trying to use a device code from client {1}", context.Request.Client.ClientId, deviceCode.ClientId);
                context.Result = new TokenRequestValidationResult(context.Request, OidcConstants.TokenErrors.InvalidGrant);
                return;
            }

            if (await _throttlingService.ShouldSlowDown(context.DeviceCode, deviceCode))
            {
                _logger.LogError("Client {0} is polling too fast", deviceCode.ClientId);
                context.Result = new TokenRequestValidationResult(context.Request, OidcConstants.TokenErrors.SlowDown);
                return;
            }

            // validate lifetime
            if (deviceCode.CreationTime.AddSeconds(deviceCode.Lifetime) < _systemClock.UtcNow)
            {
                _logger.LogError("Expired device code");
                context.Result = new TokenRequestValidationResult(context.Request, OidcConstants.TokenErrors.ExpiredToken);
                return;
            }

            // denied
            if (deviceCode.IsAuthorized &&
                (deviceCode.AuthorizedScopes == null || deviceCode.AuthorizedScopes.Any() == false))
            {
                _logger.LogError("No scopes authorized for device authorization. Access denied");
                context.Result = new TokenRequestValidationResult(context.Request, OidcConstants.TokenErrors.AccessDenied);
                return;
            }

            // make sure code is authorized
            if (!deviceCode.IsAuthorized || deviceCode.Subject == null)
            {
                context.Result = new TokenRequestValidationResult(context.Request, OidcConstants.TokenErrors.AuthorizationPending);
                return;
            }

            // make sure user is enabled
            var isActiveCtx = new IsActiveContext(deviceCode.Subject, context.Request.Client, IdentityServerConstants.ProfileIsActiveCallers.DeviceCodeValidation);
            await _profile.IsActiveAsync(isActiveCtx);

            if (isActiveCtx.IsActive == false)
            {
                _logger.LogError("User has been disabled: {subjectId}", deviceCode.Subject.GetSubjectId());
                context.Result = new TokenRequestValidationResult(context.Request, OidcConstants.TokenErrors.InvalidGrant);
                return;
            }

            context.Request.DeviceCode = deviceCode;
            context.Request.SessionId  = deviceCode.SessionId;

            context.Result = new TokenRequestValidationResult(context.Request);
            await _devices.RemoveByDeviceCodeAsync(context.DeviceCode);
        }