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()); }
/// <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); }