コード例 #1
0
        public async Task Expired_DeviceCode()
        {
            deviceCode.CreationTime = DateTime.UtcNow.AddDays(-10);
            deviceCode.Lifetime     = 300;

            var client = await _clients.FindClientByIdAsync("device_flow");

            var service = Factory.CreateDeviceCodeService();

            var handle = await service.StoreDeviceAuthorizationAsync(Guid.NewGuid().ToString(), deviceCode);

            var validator = Factory.CreateDeviceCodeValidator(service);

            var request = new ValidatedTokenRequest();

            request.SetClient(client);

            var context = new DeviceCodeValidationContext {
                DeviceCode = handle, Request = request
            };

            await validator.ValidateAsync(context);

            context.Result.IsError.Should().BeTrue();
            context.Result.Error.Should().Be(OidcConstants.TokenErrors.ExpiredToken);
        }
コード例 #2
0
        public async Task DeviceCode_Missing_Subject()
        {
            deviceCode.Subject = null;

            var client = await _clients.FindClientByIdAsync("device_flow");

            var service = Factory.CreateDeviceCodeService();

            var handle = await service.StoreDeviceAuthorizationAsync(Guid.NewGuid().ToString(), deviceCode);

            var validator = Factory.CreateDeviceCodeValidator(service);

            var request = new ValidatedTokenRequest();

            request.SetClient(client);

            var context = new DeviceCodeValidationContext {
                DeviceCode = handle, Request = request
            };

            await validator.ValidateAsync(context);

            context.Result.IsError.Should().BeTrue();
            context.Result.Error.Should().Be(OidcConstants.TokenErrors.AuthorizationPending);
        }
コード例 #3
0
        public Task ValidateAsync(DeviceCodeValidationContext context)
        {
            if (shouldError)
            {
                context.Result = new TokenRequestValidationResult(context.Request, "error");
            }
            else
            {
                context.Result = new TokenRequestValidationResult(context.Request);
            }

            return(Task.CompletedTask);
        }
コード例 #4
0
        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());
        }
コード例 #5
0
        public async Task DeviceCode_Missing()
        {
            var client = await _clients.FindClientByIdAsync("device_flow");

            var service = Factory.CreateDeviceCodeService();

            var validator = Factory.CreateDeviceCodeValidator(service);

            var request = new ValidatedTokenRequest();

            request.SetClient(client);

            var context = new DeviceCodeValidationContext {
                DeviceCode = null, Request = request
            };

            await validator.ValidateAsync(context);

            context.Result.IsError.Should().BeTrue();
            context.Result.Error.Should().Be(OidcConstants.TokenErrors.InvalidGrant);
        }
コード例 #6
0
        public async Task Valid_DeviceCode()
        {
            var client = await _clients.FindClientByIdAsync("device_flow");

            var service = Factory.CreateDeviceCodeService();

            var handle = await service.StoreDeviceAuthorizationAsync(Guid.NewGuid().ToString(), deviceCode);

            var validator = Factory.CreateDeviceCodeValidator(service);

            var request = new ValidatedTokenRequest();

            request.SetClient(client);

            var context = new DeviceCodeValidationContext {
                DeviceCode = handle, Request = request
            };

            await validator.ValidateAsync(context);

            context.Result.IsError.Should().BeFalse();
        }
コード例 #7
0
        public async Task DeviceCode_From_Different_Client()
        {
            var badActor = await _clients.FindClientByIdAsync("codeclient");

            var service = Factory.CreateDeviceCodeService();

            var handle = await service.StoreDeviceAuthorizationAsync(Guid.NewGuid().ToString(), deviceCode);

            var validator = Factory.CreateDeviceCodeValidator(service);

            var request = new ValidatedTokenRequest();

            request.SetClient(badActor);

            var context = new DeviceCodeValidationContext {
                DeviceCode = handle, Request = request
            };

            await validator.ValidateAsync(context);

            context.Result.IsError.Should().BeTrue();
            context.Result.Error.Should().Be(OidcConstants.TokenErrors.InvalidGrant);
        }
コード例 #8
0
        public async Task DeviceCode_Polling_Too_Fast()
        {
            var client = await _clients.FindClientByIdAsync("device_flow");

            var service = Factory.CreateDeviceCodeService();

            var handle = await service.StoreDeviceAuthorizationAsync(Guid.NewGuid().ToString(), deviceCode);

            var validator = Factory.CreateDeviceCodeValidator(service, throttlingService: new TestDeviceFlowThrottlingService(true));

            var request = new ValidatedTokenRequest();

            request.SetClient(client);

            var context = new DeviceCodeValidationContext {
                DeviceCode = handle, Request = request
            };

            await validator.ValidateAsync(context);

            context.Result.IsError.Should().BeTrue();
            context.Result.Error.Should().Be(OidcConstants.TokenErrors.SlowDown);
        }
コード例 #9
0
        public async Task User_Disabled()
        {
            var client = await _clients.FindClientByIdAsync("device_flow");

            var service = Factory.CreateDeviceCodeService();

            var handle = await service.StoreDeviceAuthorizationAsync(Guid.NewGuid().ToString(), deviceCode);

            var validator = Factory.CreateDeviceCodeValidator(service, new TestProfileService(false));

            var request = new ValidatedTokenRequest();

            request.SetClient(client);

            var context = new DeviceCodeValidationContext {
                DeviceCode = handle, Request = request
            };

            await validator.ValidateAsync(context);

            context.Result.IsError.Should().BeTrue();
            context.Result.Error.Should().Be(OidcConstants.TokenErrors.InvalidGrant);
        }
コード例 #10
0
    private async Task <TokenRequestValidationResult> ValidateDeviceCodeRequestAsync(NameValueCollection parameters)
    {
        _logger.LogDebug("Start validation of device code request");

        /////////////////////////////////////////////
        // resource indicator not supported for device flow
        /////////////////////////////////////////////
        if (_validatedRequest.RequestedResourceIndicator != null)
        {
            LogError("Resource indicators not supported for device flow");
            return(Invalid(OidcConstants.TokenErrors.InvalidTarget));
        }

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

        //////////////////////////////////////////////////////////
        // scope validation
        //////////////////////////////////////////////////////////
        var validatedResources = await _resourceValidator.ValidateRequestedResourcesAsync(new ResourceValidationRequest
        {
            Client             = _validatedRequest.Client,
            Scopes             = _validatedRequest.DeviceCode.AuthorizedScopes,
            ResourceIndicators = null // not supported for device grant
        });

        if (!validatedResources.Succeeded)
        {
            if (validatedResources.InvalidResourceIndicators.Any())
            {
                return(Invalid(OidcConstants.AuthorizeErrors.InvalidTarget, "Invalid resource indicator."));
            }
            if (validatedResources.InvalidScopes.Any())
            {
                return(Invalid(OidcConstants.AuthorizeErrors.InvalidScope, "Invalid scope."));
            }
        }

        LicenseValidator.ValidateResourceIndicators(_validatedRequest.RequestedResourceIndicator);
        _validatedRequest.ValidatedResources = validatedResources;

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

        return(Valid());
    }
コード例 #11
0
    /// <summary>
    /// Validates the device code.
    /// </summary>
    /// <param name="context">The context.</param>
    /// <returns></returns>
    public async Task ValidateAsync(DeviceCodeValidationContext context)
    {
        using var activity = Tracing.BasicActivitySource.StartActivity("DeviceCodeValidator.Validate");

        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.UtcDateTime)
        {
            _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);
    }