AZIDP4J
我正在写AzIdP4J,该库是在Java中构建授权服务器和身份提供商的库。
这篇文章讨论了我在开发时的想法。
库作为以下示例的工作。
// Convert HTTP Request query parameters to Map
var authorizationRequestQueryParameterMap =
Map.of(
"scope", "openid item:read",
"response_type", "code",
"client_id", "xyz-client",
"redirect_uri", "https://client.example.com/callback",
"state", "abc",
"nonce", "xyz");
var authorizationRequest =
new AuthorizationRequest(
"inabajun", // authenticated user subject. Application needs to implements user authentication. If no user is authenticated, specify null.
Instant.now().getEpochSecond(),
Set.of("openid", "item:read"), // User consented scopes. Application needs to implements user consent.
authorizationRequestQueryParameterMap);
// Authorization Request
var response = azIdP.authorize(authzReq);
// Library returns what should do next so implements application's behavior.
switch (response.next) {
case redirect -> {
// Redirect to response.redirect.redirectTo
}
case additionalPage -> {
// Implements additional process like login or consent or...
}
case errorPage -> {
// Error happend but can't redirect to redirct_uri
}
}
当您想要授权服务器 /身份提供商时
当我们想要授权服务器 /身份提供商时,我们可以选择以下模式。< / p>
- 自己开发它们
- 用库开发它们
- 使用与您的应用程序一起用作授权服务器 /身份提供商的服务< / li>
- 使用独立授权服务器 /身份提供商< / li>
在刮擦开发的情况下,我们需要编写许多来源。我们需要了解规格。我们需要继续学习新的规格和趋势...
我经常觉得自己开发用户体验,但是将有关OAUTH 2.0 / OIDC(OIDC)的协议的流程委派给了库。因此,我正在开发库来构建Java中的OAuth 2.0授权服务器 / OIDC身份提供商。 (因为Spring Security Oauth已经是EOL。)
政策
我认为库最重要的是界面。
我决定采用以下政策考虑接口。
- 不依赖特定框架
- 易于发出访问令牌 / ID令牌< / li>
- 应用程序可以自己实施用户体验
- 没有数据存储实现
不要依赖特定框架
oauth 2.0 / OpenID连接取决于HTTP作为规范。因此,如果可以在没有任何其他实现的情况下使用库,则库需要直接接受HTTP请求。
但是有许多Java Web应用程序框架,我想实现一个可用于任何框架的库。
因此,Azidp4J比直接接受HTTP请求更抽象的接口。
例如,令牌请求 /令牌响应表示为以下示例。< / p>
Spring based example implementation就是这样。
@PostMapping(value = "token", consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public ResponseEntity<Map> tokenEndpoint(@RequestParam MultiValueMap<String, Object> body) {
// client authentication by the application...
// convert HTTP request query parameters to Map
var request = new TokenRequest(authenticatedClientId, body.toSingleValueMap();
// Token Request
var response =
azIdP.issueToken(request);
// convert AzIdP4J resposne to HTTP response
return ResponseEntity.status(response.status).body(response.body);
}
另一方面,AzIDP4J不支持高度依赖框架的协议中的功能。例如,我认为许多框架具有对客户端进行身份验证并由Bearer令牌授权的功能,因此Azidp4j不支持它们。
易于发行的访问令牌 / ID令牌
我决定通过授权代码流轻松实施发出每个令牌。如果支持许多功能使接口变得复杂,则AZIDP4J不支持它们。
例如,如果AzIDP4J支持UserInfo端点,则Azidp4J需要了解用户,但它使接口变得复杂,因此我不支持它。
应用程序可以自己实施用户体验
授权请求后的行为在协议中没有关闭。当授权请求有及时=登录时,该应用程序需要显示登录页面,但是如何提供身份验证的用户体验不在这些规范的范围之内。该应用程序需要提供特定于应用程序的身份验证流。 AZIDP4J希望不影响用户身份验证,同意等等用户体验...
SO AZIDP4J提供以下接口。
// authzReq has authenticated user subject but can expresses not authenticated.
var response = azIdP.authorize(authzReq);
// Library returns what should do next so implements application's behavior.
switch (response.next) {
case redirect -> {
// Redirect to response.redirect.redirectTo
}
case additionalPage -> {
// Implements additional process like login or consent or...
}
case errorPage -> {
// Error happend but can't redirect to redirct_uri
}
Authorization Request Document
没有数据存储实现
我喜欢ory/fosite接口,因此Azidp4j模仿它们。 Azidp4j需要管理令牌,因此仅提供接口,并且应用程序需要实现它们。
不支持的事情
当我实施协议时,我将希望实施任何规格,但我决定不支持控制我的动机的事情。
我决定了第一个里程碑。
- 使Azidp4J至少起作用
- 用具体示例编写文档
对于这一里程碑,我在第一个里程碑上删除了以下内容。
- 不支持所有核心规范
- 例如,请求对象
- 不支持我不理解具体需求的规格。
很难支持哪些规格。
至少使Azidp4J起作用
首先,我实施了接受授权请求,并通过令牌端点发布了访问令牌和ID令牌。我经常在实施时测试OICD Conformance Test反对我的实施。这使得进步可见,因此继续我的动力是很好的。一致性测试揭示了一些我也无法正确理解的规范。
用具体示例编写文档
我通过一致性测试,写作来源等了解了一些规格。但是我不明白库的界面是好还是坏。我想要有关图书馆的反馈,因此我编写了带有具体示例的文档。如果您提供反馈,我会很高兴。
发展过程
为了连续检查策略“不依赖特定框架”,我实施了2种示例身份框架。
这种方法有助于我对接口的决定。例如,当我考虑使用库的应用程序是否可以实现客户端身份验证时,多个实现有助于我的考虑。
具有客户实现的图书馆开发不仅仅是测试用例更好。我从后者中找不到的情况有时会出现。
结论
我正在写AzIdP4J,该库是在Java中构建授权服务器和身份提供商的库。
这篇文章谈到了我在开发时的想法。
库作为以下示例的工作。
// convert HTTP Request query parameters to Map
var authorizationRequestQueryParameterMap =
Map.of(
"scope", "openid item:read",
"response_type", "code",
"client_id", "xyz-client",
"redirect_uri", "https://client.example.com/callback",
"state", "abc",
"nonce", "xyz");
var authorizationRequest =
new AuthorizationRequest(
"inabajun", // authenticated user subject. Application needs to implements user authentication. If no user is authenticated, specify null.
Instant.now().getEpochSecond(),
Set.of("openid", "item:read"), // User consented scopes. Application needs to implements user consent.
authorizationRequestQueryParameterMap);
var response = azIdP.authorize(authzReq);
// Library returns what should do next so implements application's behavior.
switch (response.next) {
case redirect -> {
// Redirect to response.redirect.redirectTo
}
case additionalPage -> {
// Implements additional process like login or consent or...
}
case errorPage -> {
// Error happend but can't redirect to redirct_uri
}
}
我希望您的反馈。谢谢。