aspnetcore/src/ApiAuth.IS/Options/ClientBuilder.cs

246 lines
8.7 KiB
C#

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic;
using IdentityServer4;
using IdentityServer4.Models;
namespace Microsoft.AspNetCore.ApiAuthorization.IdentityServer
{
/// <summary>
/// A builder for Clients.
/// </summary>
public class ClientBuilder
{
private const string NativeAppClientRedirectUri = "urn:ietf:wg:oauth:2.0:oob";
Client _client;
private bool _built = false;
/// <summary>
/// Creates a new builder for a single page application that coexists with an authorization server.
/// </summary>
/// <param name="clientId">The client id for the single page application.</param>
/// <returns>A <see cref="ClientBuilder"/>.</returns>
public static ClientBuilder IdentityServerSPA(string clientId)
{
var client = CreateClient(clientId);
return new ClientBuilder(client)
.WithApplicationProfile(ApplicationProfiles.IdentityServerSPA)
.WithAllowedGrants(GrantTypes.Implicit)
.WithAllowedOrigins(Array.Empty<string>())
.AllowAccessTokensViaBrowser();
}
/// <summary>
/// Creates a new builder for an externally registered single page application.
/// </summary>
/// <param name="clientId">The client id for the single page application.</param>
/// <returns>A <see cref="ClientBuilder"/>.</returns>
public static ClientBuilder SPA(string clientId)
{
var client = CreateClient(clientId);
return new ClientBuilder(client)
.WithApplicationProfile(ApplicationProfiles.SPA)
.WithAllowedGrants(GrantTypes.Implicit)
.AllowAccessTokensViaBrowser();
}
/// <summary>
/// Creates a new builder for an externally registered native application.
/// </summary>
/// <param name="clientId">The client id for the native application.</param>
/// <returns>A <see cref="ClientBuilder"/>.</returns>
public static ClientBuilder NativeApp(string clientId)
{
var client = CreateClient(clientId);
return new ClientBuilder(client)
.WithApplicationProfile(ApplicationProfiles.NativeApp)
.WithAllowedGrants(GrantTypes.Code)
.WithRedirectUri(NativeAppClientRedirectUri)
.WithLogoutRedirectUri(NativeAppClientRedirectUri)
.WithPkce()
.WithoutClientSecrets()
.WithScopes(IdentityServerConstants.StandardScopes.OfflineAccess);
}
/// <summary>
/// Creates a new builder for an externally registered web application.
/// </summary>
/// <param name="clientId">The client id for the web application.</param>
/// <returns>A <see cref="ClientBuilder"/>.</returns>
internal static ClientBuilder WebApplication(string clientId)
{
var client = CreateClient(clientId);
return new ClientBuilder(client)
.WithApplicationProfile(ApplicationProfiles.WebApplication)
.WithAllowedGrants(GrantTypes.HybridAndClientCredentials)
.WithScopes(IdentityServerConstants.StandardScopes.OfflineAccess);
}
/// <summary>
/// Initializes a new instance of <see cref="ClientBuilder"/>.
/// </summary>
public ClientBuilder() : this(new Client())
{
}
/// <summary>
/// Initializes a new intance of <see cref="ClientBuilder"/>.
/// </summary>
/// <param name="client">A preconfigured client.</param>
public ClientBuilder(Client client)
{
_client = client;
}
/// <summary>
/// Updates the client id (and name) of the client.
/// </summary>
/// <param name="clientId">The new client id.</param>
/// <returns>The <see cref="ClientBuilder"/>.</returns>
public ClientBuilder WithClientId(string clientId)
{
_client.ClientId = clientId;
_client.ClientName = clientId;
return this;
}
/// <summary>
/// Sets the application profile for the client.
/// </summary>
/// <param name="profile">The the profile for the application from <see cref="ApplicationProfiles"/>.</param>
/// <returns>The <see cref="ClientBuilder"/>.</returns>
public ClientBuilder WithApplicationProfile(string profile)
{
_client.Properties.Add(ApplicationProfilesPropertyNames.Profile, profile);
return this;
}
/// <summary>
/// Adds the <paramref name="scopes"/> to the list of allowed scopes for the client.
/// </summary>
/// <param name="scopes">The list of scopes.</param>
/// <returns>The <see cref="ClientBuilder"/>.</returns>
public ClientBuilder WithScopes(params string[] scopes)
{
foreach (var scope in scopes)
{
_client.AllowedScopes.Add(scope);
}
return this;
}
/// <summary>
/// Adds the <paramref name="redirectUri"/> to the list of valid redirect uris for the client.
/// </summary>
/// <param name="redirectUri">The redirect uri to add.</param>
/// <returns>The <see cref="ClientBuilder"/>.</returns>
public ClientBuilder WithRedirectUri(string redirectUri)
{
_client.RedirectUris.Add(redirectUri);
return this;
}
/// <summary>
/// Adds the <paramref name="logoutUri"/> to the list of valid logout redirect uris for the client.
/// </summary>
/// <param name="logoutUri">The logout uri to add.</param>
/// <returns>The <see cref="ClientBuilder"/>.</returns>
public ClientBuilder WithLogoutRedirectUri(string logoutUri)
{
_client.PostLogoutRedirectUris.Add(logoutUri);
return this;
}
/// <summary>
/// Adds the <paramref name="clientSecret"/> to the list of client secrets for the client and configures the client to
/// require using the secret when getting tokens from the token endpoint.
/// </summary>
/// <param name="clientSecret">The client secret to add.</param>
/// <returns>The <see cref="ClientBuilder"/>.</returns>
internal ClientBuilder WithClientSecret(string clientSecret)
{
_client.ClientSecrets.Add(new Secret(clientSecret));
_client.RequireClientSecret = true;
return this;
}
/// <summary>
/// Removes any configured client secret from the client and configures it to not require a client secret for getting tokens
/// from the token endpoint.
/// </summary>
/// <returns>The <see cref="ClientBuilder"/>.</returns>
public ClientBuilder WithoutClientSecrets()
{
_client.RequireClientSecret = false;
_client.ClientSecrets.Clear();
return this;
}
/// <summary>
/// Builds the client.
/// </summary>
/// <returns>The built <see cref="Client"/>.</returns>
public Client Build()
{
if (_built)
{
throw new InvalidOperationException("Client already built.");
}
_built = true;
return _client;
}
internal ClientBuilder WithPkce()
{
_client.RequirePkce = true;
_client.AllowPlainTextPkce = false;
return this;
}
internal ClientBuilder FromConfiguration()
{
_client.Properties[ApplicationProfilesPropertyNames.Source] = ApplicationProfilesPropertyValues.Configuration;
return this;
}
internal ClientBuilder WithAllowedGrants(ICollection<string> grants)
{
_client.AllowedGrantTypes = grants;
return this;
}
internal ClientBuilder WithAllowedOrigins(params string[] origins)
{
_client.AllowedCorsOrigins = origins;
return this;
}
internal ClientBuilder AllowAccessTokensViaBrowser()
{
_client.AllowAccessTokensViaBrowser = true;
return this;
}
private static Client CreateClient(string name)
{
var client = new Client
{
ClientId = name,
ClientName = name,
RequireConsent = false
};
return client;
}
}
}