OpenIddict
認証ライブラリ
OpenIddict
概要
OpenIddictは、.NETアプリケーション向けの柔軟で汎用性の高いOAuth 2.0/OpenID Connectスタックです。
詳細
OpenIddictは、.NETアプリケーションでOAuth 2.0およびOpenID Connectプロトコルの実装を提供するモダンな認証フレームワークです。Microsoftが開発し、オープンソースとして提供されています。OpenIddictは3つの独立したスタック(サーバー、クライアント、バリデーション)を提供し、開発者のニーズに応じて個別に設定できます。プロトコルレベルでの完全なコントロールを提供し、カスタム認証ロジックの実装を可能にします。Entity Framework Core、MongoDB、カスタムプロバイダーなど複数のデータストレージオプションをサポートし、ASP.NET CoreやOWIN/Katanaなど様々なホスティングプラットフォームと統合できます。OpenIddictは認証プロセスのOAuth 2.0/OpenID Connect側面にのみ焦点を当て、ユーザー認証は実装者に委ねることで高い柔軟性を実現しています。
メリット・デメリット
メリット
- プロトコル準拠: OAuth 2.0とOpenID Connectの完全実装
- 高い柔軟性: 3つの独立したスタック(サーバー、クライアント、バリデーション)
- 複数フロー対応: 認可コード、クライアントクレデンシャル、ハイブリッドフローなど全対応
- ストレージ抽象化: Entity Framework、MongoDB、カスタムプロバイダー対応
- プラットフォーム独立: ASP.NET Core、OWIN対応
- エンタープライズ対応: 大規模アプリケーションでの実用性
- OpenID Connect認証: 認証プロバイダー認証ツールでの認証実装対応
デメリット
- 学習コスト: OAuth 2.0/OpenID Connect知識が必要
- 設定複雑さ: 高度な機能には詳細な設定が必要
- ドキュメント: 高度な用途では詳細なドキュメント参照が必要
- デバッグ難易度: プロトコルレベルの問題の診断が困難
- .NET依存: .NET エコシステム外では使用不可
主要リンク
書き方の例
基本的なサーバー設定
// Program.cs または Startup.cs
services.AddOpenIddict()
.AddServer(options =>
{
// エンドポイントの設定
options.SetTokenEndpointUris("connect/token")
.SetAuthorizationEndpointUris("connect/authorize");
// グラントタイプの有効化
options.AllowAuthorizationCodeFlow()
.AllowClientCredentialsFlow()
.AllowRefreshTokenFlow();
// 開発用証明書の追加
options.AddDevelopmentEncryptionCertificate()
.AddDevelopmentSigningCertificate();
// ASP.NET Core統合
options.UseAspNetCore()
.EnableTokenEndpointPassthrough()
.EnableAuthorizationEndpointPassthrough();
});
クライアント設定(外部プロバイダー)
services.AddOpenIddict()
.AddClient(options =>
{
// 認可コードフローの有効化
options.AllowAuthorizationCodeFlow();
// 暗号化証明書の設定
options.AddDevelopmentEncryptionCertificate()
.AddDevelopmentSigningCertificate();
// ASP.NET Core統合
options.UseAspNetCore()
.EnableRedirectionEndpointPassthrough();
// System.Net.Http統合
options.UseSystemNetHttp();
// GitHub統合
options.UseWebProviders()
.AddGitHub(options =>
{
options.SetClientId("your-client-id")
.SetClientSecret("your-client-secret")
.SetRedirectUri("callback/login/github");
});
});
トークン検証設定
services.AddOpenIddict()
.AddValidation(options =>
{
// OpenID Connect Discovery使用
options.SetIssuer("https://localhost:44319/");
// 暗号化キーの設定
options.AddEncryptionKey(new SymmetricSecurityKey(
Convert.FromBase64String("your-encryption-key")));
// System.Net.Http統合
options.UseSystemNetHttp();
// ASP.NET Core統合
options.UseAspNetCore();
});
認証コントローラー
[ApiController]
public class AuthorizationController : ControllerBase
{
[HttpPost("~/connect/token")]
public async Task<IActionResult> Exchange()
{
var request = HttpContext.GetOpenIddictServerRequest();
if (request.IsClientCredentialsGrantType())
{
var identity = new ClaimsIdentity(
TokenValidationParameters.DefaultAuthenticationType,
Claims.Name,
Claims.Role);
identity.SetClaim(Claims.Subject, request.ClientId);
identity.SetClaim(Claims.Name, "API Client");
identity.SetDestinations(static claim => claim.Type switch
{
Claims.Name when claim.Subject.HasScope(Scopes.Profile)
=> new[] { Destinations.AccessToken, Destinations.IdentityToken },
_ => new[] { Destinations.AccessToken }
});
return SignIn(new ClaimsPrincipal(identity),
OpenIddictServerAspNetCoreDefaults.AuthenticationScheme);
}
throw new NotImplementedException("The specified grant is not implemented.");
}
}
クライアントクレデンシャルフロー使用
// DIコンテナからサービス取得
var service = serviceProvider.GetRequiredService<OpenIddictClientService>();
// アクセストークン取得
var result = await service.AuthenticateWithClientCredentialsAsync(new());
var accessToken = result.AccessToken;
// APIリクエストで使用
using var httpClient = new HttpClient();
httpClient.DefaultRequestHeaders.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
var response = await httpClient.GetAsync("https://api.example.com/data");
アプリケーション登録(プログラム)
public class Worker : IHostedService
{
private readonly IServiceProvider _serviceProvider;
public async Task StartAsync(CancellationToken cancellationToken)
{
using var scope = _serviceProvider.CreateScope();
var manager = scope.ServiceProvider
.GetRequiredService<IOpenIddictApplicationManager>();
if (await manager.FindByClientIdAsync("api-client") is null)
{
await manager.CreateAsync(new OpenIddictApplicationDescriptor
{
ClientId = "api-client",
ClientSecret = "your-client-secret",
Permissions =
{
Permissions.Endpoints.Token,
Permissions.GrantTypes.ClientCredentials,
Permissions.Scopes.Profile
}
});
}
}
}
高度な設定(カスタムイベントハンドラー)
services.AddOpenIddict()
.AddServer(options =>
{
options.AddEventHandler<HandleConfigurationRequestContext>(builder =>
builder.UseInlineHandler(context =>
{
// カスタムメタデータの追加
context.Metadata["custom_metadata"] = "custom_value";
return default;
}));
});