跳到主要内容

IGeekFan.OpenIddict.FreeSql

OpenIddict 的 FreeSql 存储实现,用于 OAuth2/OIDC 授权服务。

功能概览

功能说明
授权服务构建 OAuth2/OIDC 授权服务器
FreeSql 存储OpenIddict 数据持久化到关系型数据库
授权码/令牌支持授权码、客户端凭证等授权流程
用户信息UserInfo 端点支持

安装

dotnet add package IGeekFan.OpenIddict.FreeSql

快速开始

场景:OAuth2 授权服务

1. 配置 FreeSql

using IGeekFan.OpenIddict.FreeSql;

var builder = WebApplication.CreateBuilder(args);

var fsql = new FreeSqlBuilder()
.UseConnectionString(DataType.MySql, builder.Configuration.GetConnectionString("Default"))
.Build();

builder.Services.AddSingleton(fsql);

2. 配置 OpenIddict

builder.Services.AddOpenIddict()
.AddCore(options => options.AddFreeSqlStores())
.AddServer(options =>
{
options.SetAuthorizationEndpointUris("/connect/authorize")
.SetTokenEndpointUris("/connect/token")
.SetUserInfoEndpointUris("/connect/userinfo");

options.AllowAuthorizationCodeFlow()
.AllowRefreshTokenFlow();

options.UseAspNetCore()
.EnableAuthorizationEndpointPassthrough()
.EnableTokenEndpointPassthrough();
})
.AddValidation(options =>
{
options.UseAspNetCore();
});

3. 同步表结构

var app = builder.Build();

// 同步 OpenIddict 表结构
using (var scope = app.Services.CreateScope())
{
var fsql = scope.ServiceProvider.GetRequiredService<IFreeSql>();
fsql.SyncOpenIddictTables();
}

app.Run();

场景:创建 OAuth2 应用

// 创建应用
var application = new OpenIddictApplication
{
ClientId = "my-app",
ClientSecret = "secret",
DisplayName = "My Application",
Permissions = new[]
{
OpenIddictConstants.Permissions.Endpoints.Authorization,
OpenIddictConstants.Permissions.Endpoints.Token,
OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode,
OpenIddictConstants.Permissions.Scopes.Email,
OpenIddictConstants.Permissions.Scopes.Profile,
OpenIddictConstants.Permissions.Scopes.Roles,
OpenIddictConstants.Perscopes.OpenId
}
};

await applicationManager.CreateAsync(application);

高级配置

自定义 Scope

var scope = new OpenIddictScope
{
Name = "api",
DisplayName = "API Access",
Resources = new[] { "api" }
};

await scopeManager.CreateAsync(scope);

自定义声明

builder.Services.AddOpenIddict()
.AddServer(options =>
{
options.Configure(context =>
{
context.Settings["OpenIddict:Claims:sub"] = "UserId";
context.Settings["OpenIddict:Claims:name"] = "UserName";
context.Settings["OpenIddict:Claims:email"] = "Email";
});
});

令牌生命周期

builder.Services.AddOpenIddict()
.AddServer(options =>
{
options.Configure(context =>
{
context.Settings["OpenIddict:Tokens:AccessTokenLifetime"] = "01:00:00";
context.Settings["OpenIddict:Tokens:RefreshTokenLifetime"] = "7.00:00:00";
});
});

数据表

表名说明
open_iddict_application客户端应用
open_iddict_authorization用户授权记录
open_iddict_scopeScope 定义
open_iddict_tokenToken 令牌

API 示例

授权码流程

// 1. 重定向到授权端点
const authUrl = `${authServer}/connect/authorize?` +
`client_id=${clientId}&` +
`redirect_uri=${redirectUri}&` +
`response_type=code&` +
`scope=openid profile email&` +
`code_challenge=${challenge}&` +
`code_challenge_method=S256`;

// 2. 用户授权后,获取授权码
// 3. 用授权码换取令牌
const tokenResponse = await fetch(`${authServer}/connect/token`, {
method: 'POST',
headers: { 'Content-Type': 'application/x-www-form-urlencoded' },
body: new URLSearchParams({
grant_type: 'authorization_code',
code: authorizationCode,
redirect_uri: redirectUri,
code_verifier: verifier,
client_id: clientId,
client_secret: clientSecret
})
});

运维建议

建议说明
安全使用 HTTPS
密钥管理定期轮换签名证书
监控监控令牌颁发和使用
备份定期备份授权数据

故障排查

问题解决方案
表未创建确保调用 SyncOpenIddictTables
令牌无效检查签名证书配置
授权失败检查应用权限配置
连接失败检查数据库连接

相关文档