/// <inheritdoc/>
        public virtual IAsyncEnumerable <TApplication> FindByRedirectUriAsync(
            string address, CancellationToken cancellationToken)
        {
            if (string.IsNullOrEmpty(address))
            {
                throw new ArgumentException(SR.GetResourceString(SR.ID0143), nameof(address));
            }

            return(ExecuteAsync(cancellationToken));

            async IAsyncEnumerable <TApplication> ExecuteAsync([EnumeratorCancellation] CancellationToken cancellationToken)
Esempio n. 2
0
        /// <inheritdoc/>
        public IAsyncEnumerable <TScope> FindByNamesAsync(ImmutableArray <string> names, CancellationToken cancellationToken)
        {
            if (names.Any(name => string.IsNullOrEmpty(name)))
            {
                throw new ArgumentException(SR.GetResourceString(SR.ID0203), nameof(names));
            }

            // Note: this method is only partially cached.

            return(ExecuteAsync(cancellationToken));

            async IAsyncEnumerable <TScope> ExecuteAsync([EnumeratorCancellation] CancellationToken cancellationToken)
Esempio n. 3
0
        /// <inheritdoc/>
        public virtual async ValueTask <TScope?> FindByNameAsync(string name, CancellationToken cancellationToken)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentException(SR.GetResourceString(SR.ID0202), nameof(name));
            }

            return((await GetDatabase()
                    .GetViewAsync(OpenIddictViews.Scope <TScope> .Name, new() { IncludeDocs = true }, cancellationToken))
                   .FirstOrDefault()
                   ?.Document);
        }
        public void ReplaceApplicationStoreResolver_ThrowsAnExceptionForInvalidStoreResolver()
        {
            // Arrange
            var services = CreateServices();
            var builder  = CreateBuilder(services);

            // Act and assert
            var exception = Assert.Throws <ArgumentException>(() => builder.ReplaceApplicationStoreResolver(typeof(object)));

            Assert.Equal("type", exception.ParamName);
            Assert.StartsWith(SR.GetResourceString(SR.ID1231), exception.Message);
        }
        public void Get_ThrowsAnExceptionWhenStoreCannotBeFound()
        {
            // Arrange
            var services = new ServiceCollection();
            var provider = services.BuildServiceProvider();
            var resolver = new OpenIddictTokenStoreResolver(provider);

            // Act and assert
            var exception = Assert.Throws <InvalidOperationException>(() => resolver.Get <OpenIddictToken>());

            Assert.Equal(SR.GetResourceString(SR.ID0231), exception.Message);
        }
        /// <inheritdoc/>
        public virtual async ValueTask <TScope?> FindByIdAsync(string identifier, CancellationToken cancellationToken)
        {
            if (string.IsNullOrEmpty(identifier))
            {
                throw new ArgumentException(SR.GetResourceString(SR.ID0195), nameof(identifier));
            }

            var database = await Context.GetDatabaseAsync(cancellationToken);

            var collection = database.GetCollection <TScope>(Options.CurrentValue.ScopesCollectionName);

            return(await collection.Find(scope => scope.Id == ObjectId.Parse(identifier)).FirstOrDefaultAsync(cancellationToken));
        }
        /// <inheritdoc/>
        public virtual async ValueTask <TApplication?> FindByClientIdAsync(string identifier, CancellationToken cancellationToken)
        {
            if (string.IsNullOrEmpty(identifier))
            {
                throw new ArgumentException(SR.GetResourceString(SR.ID0195), nameof(identifier));
            }

            var database = await Context.GetDatabaseAsync(cancellationToken);

            var collection = database.GetCollection <TApplication>(Options.CurrentValue.ApplicationsCollectionName);

            return(await collection.Find(application => application.ClientId == identifier).FirstOrDefaultAsync(cancellationToken));
        }
        /// <inheritdoc/>
        public virtual async ValueTask <TScope?> FindByNameAsync(string name, CancellationToken cancellationToken)
        {
            if (string.IsNullOrEmpty(name))
            {
                throw new ArgumentException(SR.GetResourceString(SR.ID0202), nameof(name));
            }

            var database = await Context.GetDatabaseAsync(cancellationToken);

            var collection = database.GetCollection <TScope>(Options.CurrentValue.ScopesCollectionName);

            return(await collection.Find(scope => scope.Name == name).FirstOrDefaultAsync(cancellationToken));
        }
Esempio n. 9
0
    public void Get_ThrowsAnExceptionForInvalidEntityType()
    {
        // Arrange
        var services = new ServiceCollection();

        var provider = services.BuildServiceProvider();
        var resolver = new OpenIddictMongoDbAuthorizationStoreResolver(provider);

        // Act and assert
        var exception = Assert.Throws <InvalidOperationException>(() => resolver.Get <CustomAuthorization>());

        Assert.Equal(SR.GetResourceString(SR.ID0258), exception.Message);
    }
Esempio n. 10
0
        public async Task ExtractLogoutRequest_UnexpectedMethodReturnsAnError(string method)
        {
            // Arrange
            await using var server = await CreateServerAsync(options => options.EnableDegradedMode());

            await using var client = await server.CreateClientAsync();

            // Act
            var response = await client.SendAsync(method, "/connect/logout", new OpenIddictRequest());

            // Assert
            Assert.Equal(Errors.InvalidRequest, response.Error);
            Assert.Equal(SR.GetResourceString(SR.ID3084), response.ErrorDescription);
        }
Esempio n. 11
0
    public void Get_ThrowsAnExceptionForInvalidEntityType()
    {
        // Arrange
        var services = new ServiceCollection();

        var options  = Mock.Of <IOptionsMonitor <OpenIddictEntityFrameworkCoreOptions> >();
        var provider = services.BuildServiceProvider();
        var resolver = new OpenIddictEntityFrameworkCoreScopeStoreResolver(new TypeResolutionCache(), options, provider);

        // Act and assert
        var exception = Assert.Throws <InvalidOperationException>(() => resolver.Get <CustomScope>());

        Assert.Equal(SR.GetResourceString(SR.ID0255), exception.Message);
    }
        /// <inheritdoc/>
        public virtual async ValueTask UpdateAsync(TApplication application,
                                                   CancellationToken cancellationToken)
        {
            Check.NotNull(application, nameof(application));

            try
            {
                await GetDatabase().AddOrUpdateAsync(application, cancellationToken: cancellationToken);
            }
            catch (CouchConflictException ex)
            {
                throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID0239), ex);
            }
        }
Esempio n. 13
0
        /// <inheritdoc/>
        public virtual async ValueTask DeleteAsync(TScope scope, CancellationToken cancellationToken)
        {
            Check.NotNull(scope, nameof(scope));

            var db = GetDatabase();

            try
            {
                await db.RemoveAsync(scope, cancellationToken : cancellationToken);
            }
            catch (CouchConflictException ex)
            {
                throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID0245), ex);
            }
        }
Esempio n. 14
0
    /// <inheritdoc/>
    public IAsyncEnumerable <TToken> FindAsync(string subject, string client, CancellationToken cancellationToken)
    {
        if (string.IsNullOrEmpty(subject))
        {
            throw new ArgumentException(SR.GetResourceString(SR.ID0198), nameof(subject));
        }

        if (string.IsNullOrEmpty(client))
        {
            throw new ArgumentException(SR.GetResourceString(SR.ID0124), nameof(client));
        }

        return(ExecuteAsync(cancellationToken));

        async IAsyncEnumerable <TToken> ExecuteAsync([EnumeratorCancellation] CancellationToken cancellationToken)
Esempio n. 15
0
    public async Task ExtractUserinfoRequest_UnexpectedMethodReturnsAnError(string method)
    {
        // Arrange
        await using var server = await CreateServerAsync();

        await using var client = await server.CreateClientAsync();

        // Act
        var response = await client.SendAsync(method, "/connect/userinfo", new OpenIddictRequest());

        // Assert
        Assert.Equal(Errors.InvalidRequest, response.Error);
        Assert.Equal(SR.GetResourceString(SR.ID2084), response.ErrorDescription);
        Assert.Equal(SR.FormatID8000(SR.ID2084), response.ErrorUri);
    }
        public void SetDefaultTokenEntity_ThrowsAnExceptionForInvalidType()
        {
            // Arrange
            var services = CreateServices();
            var builder  = CreateBuilder(services);

            // Act and assert
            var exception = Assert.Throws <ArgumentException>(delegate
            {
                return(builder.SetDefaultTokenEntity(typeof(long)));
            });

            Assert.Equal("type", exception.ParamName);
            Assert.StartsWith(SR.GetResourceString(SR.ID1231), exception.Message);
        }
Esempio n. 17
0
            /// <inheritdoc/>
            public ValueTask HandleAsync(ValidateUserinfoRequestContext context)
            {
                if (context is null)
                {
                    throw new ArgumentNullException(nameof(context));
                }

                if (string.IsNullOrEmpty(context.Request.AccessToken))
                {
                    context.Logger.LogInformation(SR.GetResourceString(SR.ID6131), Parameters.AccessToken);

                    context.Reject(
                        error: Errors.MissingToken,
                        description: SR.FormatID2029(Parameters.AccessToken),
                        uri: SR.FormatID8000(SR.ID2029));

                    return(default);
        /// <inheritdoc/>
        public virtual async ValueTask DeleteAsync(TToken token, CancellationToken cancellationToken)
        {
            if (token == null)
            {
                throw new ArgumentNullException(nameof(token));
            }

            var database = await Context.GetDatabaseAsync(cancellationToken);

            var collection = database.GetCollection <TToken>(Options.CurrentValue.TokensCollectionName);

            if ((await collection.DeleteOneAsync(entity =>
                                                 entity.Id == token.Id &&
                                                 entity.ConcurrencyToken == token.ConcurrencyToken)).DeletedCount == 0)
            {
                throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID1246));
            }
        }
        /// <inheritdoc/>
        public virtual async ValueTask <TApplication?> FindByClientIdAsync(string identifier, CancellationToken cancellationToken)
        {
            if (string.IsNullOrEmpty(identifier))
            {
                throw new ArgumentException(SR.GetResourceString(SR.ID0195), nameof(identifier));
            }

            var part = $"type({Options.CurrentValue.ApplicationTypeName}))";

            var query = "query Q($clientId: string)" + Options.CurrentValue.ApplicationFullQuery
                        .Replace(part, $"eq(oidc_client_id, $clientId)) @filter({part}");

            var database = await Context.GetDatabaseAsync(cancellationToken);

            using var txn = (Txn)database.NewTransaction(true, true, cancellationToken);

            var result = await txn.QueryWithVars <TApplication>("oidc_application", query, new()
            {
Esempio n. 20
0
    public async Task Execute_UnschedulesTriggersWhenAuthorizationManagerIsMissing()
    {
        // Arrange
        var provider = Mock.Of <IServiceProvider>(provider =>
                                                  provider.GetService(typeof(IOpenIddictAuthorizationManager)) == null);

        var job = CreateJob(provider);

        // Act and assert
        var exception = await Assert.ThrowsAsync <JobExecutionException>(() => job.Execute(Mock.Of <IJobExecutionContext>()));

        Assert.False(exception.RefireImmediately);
        Assert.True(exception.UnscheduleAllTriggers);
        Assert.True(exception.UnscheduleFiringTrigger);

        Assert.IsType <InvalidOperationException>(exception.InnerException);
        Assert.Equal(SR.GetResourceString(SR.ID0278), exception.InnerException !.Message);
    }
Esempio n. 21
0
            /// <inheritdoc/>
            public ValueTask HandleAsync(ValidateRevocationRequestContext context)
            {
                if (context is null)
                {
                    throw new ArgumentNullException(nameof(context));
                }

                // Reject revocation requests missing the mandatory token parameter.
                if (string.IsNullOrEmpty(context.Request.Token))
                {
                    context.Logger.LogInformation(SR.GetResourceString(SR.ID6111), Parameters.Token);

                    context.Reject(
                        error: Errors.InvalidRequest,
                        description: SR.FormatID2029(Parameters.Token),
                        uri: SR.FormatID8000(SR.ID2029));

                    return(default);
        /// <summary>
        /// Creates a new scope.
        /// </summary>
        /// <param name="scope">The scope to create.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
        /// <returns>
        /// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation.
        /// </returns>
        public virtual async ValueTask CreateAsync(TScope scope, CancellationToken cancellationToken = default)
        {
            if (scope is null)
            {
                throw new ArgumentNullException(nameof(scope));
            }

            var results = await GetValidationResultsAsync(scope, cancellationToken);

            if (results.Any(result => result != ValidationResult.Success))
            {
                var builder = new StringBuilder();
                builder.AppendLine(SR.GetResourceString(SR.ID0222));
                builder.AppendLine();

                foreach (var result in results)
                {
                    builder.AppendLine(result.ErrorMessage);
                }

                throw new OpenIddictExceptions.ValidationException(builder.ToString(), results);
            }

            await Store.CreateAsync(scope, cancellationToken);

            if (!Options.CurrentValue.DisableEntityCaching)
            {
                await Cache.AddAsync(scope, cancellationToken);
            }

            async Task <ImmutableArray <ValidationResult> > GetValidationResultsAsync(
                TScope scope, CancellationToken cancellationToken)
            {
                var builder = ImmutableArray.CreateBuilder <ValidationResult>();

                await foreach (var result in ValidateAsync(scope, cancellationToken))
                {
                    builder.Add(result);
                }

                return(builder.ToImmutable());
            }
        }
Esempio n. 23
0
    public void Get_ThrowsAnExceptionWhenDbContextTypeIsNotAvailable()
    {
        // Arrange
        var services = new ServiceCollection();

        var options = Mock.Of <IOptionsMonitor <OpenIddictEntityFrameworkCoreOptions> >(
            mock => mock.CurrentValue == new OpenIddictEntityFrameworkCoreOptions
        {
            DbContextType = null
        });

        var provider = services.BuildServiceProvider();
        var resolver = new OpenIddictEntityFrameworkCoreScopeStoreResolver(new TypeResolutionCache(), options, provider);

        // Act and assert
        var exception = Assert.Throws <InvalidOperationException>(() => resolver.Get <OpenIddictEntityFrameworkCoreScope>());

        Assert.Equal(SR.GetResourceString(SR.ID0253), exception.Message);
    }
Esempio n. 24
0
    public void AddCore_ResolvingUntypedTokenManagerThrowsAnExceptionWhenDefaultEntityIsNotSet()
    {
        // Arrange
        var services = new ServiceCollection();
        var builder  = new OpenIddictBuilder(services);

        // Act
        builder.AddCore();

        // Assert
        var provider = services.BuildServiceProvider();

        var exception = Assert.Throws <InvalidOperationException>(delegate
        {
            return(provider.GetRequiredService <IOpenIddictTokenManager>());
        });

        Assert.Equal(SR.GetResourceString(SR.ID0276), exception.Message);
    }
        /// <inheritdoc/>
        public virtual async ValueTask <TApplication?> FindByClientIdAsync(string identifier,
                                                                           CancellationToken cancellationToken)
        {
            if (string.IsNullOrEmpty(identifier))
            {
                throw new ArgumentException(SR.GetResourceString(SR.ID0195), nameof(identifier));
            }

            var options = new CouchViewOptions <string>
            {
                Key         = identifier,
                IncludeDocs = true
            };

            return((await GetDatabase()
                    .GetViewAsync(OpenIddictViews.Application <TApplication> .ClientId, options, cancellationToken)
                    .ConfigureAwait(false))
                   .FirstOrDefault()
                   ?.Document);
        }
        /// <summary>
        /// Creates a new scope based on the specified descriptor.
        /// </summary>
        /// <param name="descriptor">The scope descriptor.</param>
        /// <param name="cancellationToken">The <see cref="CancellationToken"/> that can be used to abort the operation.</param>
        /// <returns>
        /// A <see cref="ValueTask"/> that can be used to monitor the asynchronous operation, whose result returns the scope.
        /// </returns>
        public virtual async ValueTask <TScope> CreateAsync(
            OpenIddictScopeDescriptor descriptor, CancellationToken cancellationToken = default)
        {
            if (descriptor is null)
            {
                throw new ArgumentNullException(nameof(descriptor));
            }

            var scope = await Store.InstantiateAsync(cancellationToken);

            if (scope is null)
            {
                throw new InvalidOperationException(SR.GetResourceString(SR.ID0223));
            }

            await PopulateAsync(scope, descriptor, cancellationToken);
            await CreateAsync(scope, cancellationToken);

            return(scope);
        }
Esempio n. 27
0
        static IReadOnlyDictionary <string, string> ReadProperties(BinaryReader reader)
        {
            // Read the version of the format used to serialize the properties.
            var version = reader.ReadInt32();

            if (version != 1)
            {
                throw new InvalidOperationException(SR.GetResourceString(SR.ID0287));
            }

            var count      = reader.ReadInt32();
            var properties = new Dictionary <string, string>(count, StringComparer.Ordinal);

            for (var index = 0; index != count; ++index)
            {
                properties.Add(reader.ReadString(), reader.ReadString());
            }

            return(properties);
        }
Esempio n. 28
0
        /// <inheritdoc/>
        public ValueTask HandleAsync(ProcessRequestContext context)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            // This handler only applies to ASP.NET Core requests. If the HTTP context cannot be resolved,
            // this may indicate that the request was incorrectly processed by another server stack.
            var request = context.Transaction.GetHttpRequest();

            if (request is null)
            {
                throw new InvalidOperationException(SR.GetResourceString(SR.ID0114));
            }

            // Only use the current host as the issuer if the
            // issuer was not explicitly set in the options.
            if (context.Issuer is not null)
            {
                return(default);
            /// <inheritdoc/>
            public ValueTask HandleAsync(ProcessAuthenticationContext context)
            {
                if (context is null)
                {
                    throw new ArgumentNullException(nameof(context));
                }

                // Note: unlike the equivalent event in the server stack, authentication can be triggered for
                // arbitrary requests (typically, API endpoints that are not owned by the validation stack).
                // As such, the token is not directly resolved from the request, that may be null at this stage.
                // Instead, the token is expected to be populated by one or multiple handlers provided by the host.
                //
                // Note: this event can also be triggered by the validation service to validate an arbitrary token.

                if (string.IsNullOrEmpty(context.Token))
                {
                    context.Reject(
                        error: Errors.MissingToken,
                        description: SR.GetResourceString(SR.ID2000));

                    return(default);
Esempio n. 30
0
        /// <inheritdoc/>
        public virtual async ValueTask DeleteAsync(TAuthorization authorization, CancellationToken cancellationToken)
        {
            if (authorization is null)
            {
                throw new ArgumentNullException(nameof(authorization));
            }

            var database = await Context.GetDatabaseAsync(cancellationToken);

            var collection = database.GetCollection <TAuthorization>(Options.CurrentValue.AuthorizationsCollectionName);

            if ((await collection.DeleteOneAsync(entity =>
                                                 entity.Id == authorization.Id &&
                                                 entity.ConcurrencyToken == authorization.ConcurrencyToken, cancellationToken)).DeletedCount == 0)
            {
                throw new OpenIddictExceptions.ConcurrencyException(SR.GetResourceString(SR.ID0241));
            }

            // Delete the tokens associated with the authorization.
            await database.GetCollection <OpenIddictMongoDbToken>(Options.CurrentValue.TokensCollectionName)
            .DeleteManyAsync(token => token.AuthorizationId == authorization.Id, cancellationToken);
        }