<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: inaba jun</title>
    <description>The latest articles on DEV Community by inaba jun (@inabajunmr).</description>
    <link>https://dev.to/inabajunmr</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F61086%2F6da5e61f-94b9-436b-8974-adc2f3179137.jpeg</url>
      <title>DEV Community: inaba jun</title>
      <link>https://dev.to/inabajunmr</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/inabajunmr"/>
    <language>en</language>
    <item>
      <title>Writing Java library to build OAuth 2.0 Authorization Server / OpenID Connect Identity Provider</title>
      <dc:creator>inaba jun</dc:creator>
      <pubDate>Thu, 22 Dec 2022 14:31:54 +0000</pubDate>
      <link>https://dev.to/inabajunmr/writing-java-library-to-build-oauth-20-authorization-server-openid-connect-identity-provider-402</link>
      <guid>https://dev.to/inabajunmr/writing-java-library-to-build-oauth-20-authorization-server-openid-connect-identity-provider-402</guid>
      <description>&lt;h2&gt;
  
  
  AzIdP4J
&lt;/h2&gt;

&lt;p&gt;I'm writing &lt;a href="https://github.com/inabajunmr/azidp4j"&gt;AzIdP4J&lt;/a&gt; that the library to build Authorization Server and Identity Provider in Java.&lt;br&gt;
The article talk about what I think while developing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/inabajunmr/azidp4j"&gt;inabajunmr/azidp4j: Library for Java OAuth 2.0 Authorization Server &amp;amp; OpenID Connect Identity Provider&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The library works as the following example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Convert HTTP Request query parameters to Map&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;authorizationRequestQueryParameterMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"scope"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"openid item:read"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"response_type"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"code"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"client_id"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"xyz-client"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"redirect_uri"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"https://client.example.com/callback"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"state"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"abc"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"nonce"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"xyz"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;authorizationRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AuthorizationRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"inabajun"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// authenticated user subject. Application needs to implements user authentication. If no user is authenticated, specify null.&lt;/span&gt;
                &lt;span class="nc"&gt;Instant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getEpochSecond&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
                &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"openid"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"item:read"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// User consented scopes. Application needs to implements user consent.&lt;/span&gt;
                &lt;span class="n"&gt;authorizationRequestQueryParameterMap&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Authorization Request&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;azIdP&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;authorize&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;authzReq&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Library returns what should do next so implements application's behavior.&lt;/span&gt;
&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;redirect&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Redirect to response.redirect.redirectTo&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;additionalPage&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Implements additional process like login or consent or...&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;errorPage&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Error happend but can't redirect to redirct_uri&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  When you want Authorization server / Identity provider
&lt;/h2&gt;

&lt;p&gt;When we want Authorization server / Identity provider, we can select the following patterns.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Develop them by yourself&lt;/li&gt;
&lt;li&gt;Develop them with libraries&lt;/li&gt;
&lt;li&gt;Use a service that works as an Authorization server / Identity provider in conjunction with your application&lt;/li&gt;
&lt;li&gt;Using standalone Authorization server / Identity provider&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the case of scratch development, we need to write many sources. We need to understand the specifications. We need to continue learning about new specifications and trends...&lt;/p&gt;

&lt;p&gt;I often feel to develop user experiences myself but delegating processes about protocols like OAuth 2.0 / OIDC to a library. So I'm developing the library to build OAuth 2.0 Authorization Server / OIDC Identity Provider in Java. (Because Spring Security OAuth was EOL already.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Policies
&lt;/h2&gt;

&lt;p&gt;I think the most important thing about libraries is the interface.&lt;br&gt;
I decided on the following policies to consider interfaces.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Don't depend on a specific framework&lt;/li&gt;
&lt;li&gt;Easy to issue Access token / ID token&lt;/li&gt;
&lt;li&gt;Applications can implement user experiences by themselves&lt;/li&gt;
&lt;li&gt;No datastore implementations&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  Don't depend on a specific framework
&lt;/h3&gt;

&lt;p&gt;OAuth 2.0 / OpenID Connect depends on HTTP as a specification. So if a library can be used without any additional implementations, the library needs to accept HTTP requests directly.&lt;/p&gt;

&lt;p&gt;But there are many Java web application frameworks and I want to implement a library that can be used for any framework.&lt;/p&gt;

&lt;p&gt;So AzIdP4J has more abstract interfaces than accepting HTTP requests directly.&lt;/p&gt;

&lt;p&gt;For example, token request / token response is expressed as following examples.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/inabajunmr/azidp4j/blob/main/azidp4j/src/main/java/org/azidp4j/token/request/TokenRequest.java"&gt;TokenRequest&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/inabajunmr/azidp4j/blob/main/azidp4j/src/main/java/org/azidp4j/token/response/TokenResponse.java"&gt;TokenResponse&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://github.com/inabajunmr/azidp4j/blob/main/azidp4j-spring-security-sample/src/main/java/org/azidp4j/springsecuritysample/handler/TokenEndpointHandler.java#L50"&gt;Spring based example implementation&lt;/a&gt; is like this.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="nd"&gt;@PostMapping&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"token"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;consumes&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MediaType&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;APPLICATION_FORM_URLENCODED_VALUE&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;tokenEndpoint&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nd"&gt;@RequestParam&lt;/span&gt; &lt;span class="nc"&gt;MultiValueMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nc"&gt;String&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="nc"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;

    &lt;span class="c1"&gt;// client authentication by the application...&lt;/span&gt;
    &lt;span class="c1"&gt;// convert HTTP request query parameters to Map&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;request&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;TokenRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;authenticatedClientId&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;toSingleValueMap&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;
    &lt;span class="c1"&gt;// Token Request&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
            &lt;span class="n"&gt;azIdP&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;issueToken&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;request&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;

    &lt;span class="c1"&gt;// convert AzIdP4J resposne to HTTP response&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nc"&gt;ResponseEntity&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;status&lt;/span&gt;&lt;span class="o"&gt;).&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;body&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;On the other hand, AzIdP4J doesn't support functions within the protocol that be highly dependent on the framework. For example, I think many frameworks have functions to authenticate a client and authorize by bearer token so AzIdP4J doesn't support them.&lt;/p&gt;

&lt;h3&gt;
  
  
  Easy to issue Access token / ID token
&lt;/h3&gt;

&lt;p&gt;I decided to make it easy to implement issuing each token by Authorization Code Flow. If supporting many functions makes interfaces complicated, AzIdP4J doesn't support them.&lt;/p&gt;

&lt;p&gt;For example, if AzIdP4J supports the UserInfo endpoint, AzIdP4J needs to know Users but it makes interfaces complicated so I don't support it yet.&lt;/p&gt;

&lt;h3&gt;
  
  
  Applications can implement user experiences by themselves
&lt;/h3&gt;

&lt;p&gt;Behavior after authorization request doesn't close in protocols. When the authorization request has prompt=login, the application needs to show a login page but how to provide authentication user experiences are out of the scope of these specifications. The application needs to provide the application-specific authentication flow. AzIdP4J wants not to affect user experiences like user authentication, consent, etc...&lt;/p&gt;

&lt;p&gt;So AzIdP4J provides the following interface.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// authzReq has authenticated user subject but can expresses not authenticated.&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;azIdP&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;authorize&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;authzReq&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Library returns what should do next so implements application's behavior.&lt;/span&gt;
&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;redirect&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Redirect to response.redirect.redirectTo&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;additionalPage&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Implements additional process like login or consent or...&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;errorPage&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Error happend but can't redirect to redirct_uri&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/inabajunmr/azidp4j/blob/main/docs/endpoint-implementations.md#authorization-request"&gt;Authorization Request Document&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  No datastore implementations
&lt;/h3&gt;

&lt;p&gt;I like &lt;a href="https://github.com/ory/fosite"&gt;ory/fosite&lt;/a&gt; interfaces so AzIdP4J imitates them. AzIdP4J needs to manage tokens so it provides only interfaces and an Application needs to implement them.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/inabajunmr/azidp4j/blob/main/docs/config.md#token-stores-configuration"&gt;Token Stores Configuration&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Things not to support
&lt;/h2&gt;

&lt;p&gt;When I implement protocols, I become to wish to implement any specifications but I decided on things that don't support to control my motivation.&lt;/p&gt;

&lt;p&gt;I decided first milestones.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make AzIdP4J work at least&lt;/li&gt;
&lt;li&gt;Writing documents with concrete examples&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For the milestone, I removed the following things at the first milestone.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Doesn't support all of the core specification

&lt;ul&gt;
&lt;li&gt;For example, Request Object&lt;/li&gt;
&lt;li&gt;Doesn't support specifications that I don't understand concrete demands.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's difficult what specifications should be supported.&lt;/p&gt;

&lt;h3&gt;
  
  
  Make AzIdP4J work at least
&lt;/h3&gt;

&lt;p&gt;First of all, I implemented accepting authorization requests and issuing access tokens and ID tokens via the token endpoint. I often test &lt;a href="https://openid.net/certification/testing/"&gt;OICD Conformance Test&lt;/a&gt; against my implementation while implementing. This made progress visible so It was good to continue my motivation. The conformance test revealed some specifications that I can't understand correctly also.&lt;/p&gt;

&lt;h3&gt;
  
  
  Writing documents with concrete examples
&lt;/h3&gt;

&lt;p&gt;I understood some of the specifications through conformance tests, writing sources and so one. But I can't understand whether the library's interfaces are good or bad. I want feedback about the library so I wrote documents with concrete examples. I'll be glad if you provide feedback.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/inabajunmr/azidp4j/tree/main/docs"&gt;AzIdP4J Documentation&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Development process
&lt;/h2&gt;

&lt;p&gt;For continuous checking of the policy "Don't depend on a specific framework", I implemented 2 types of sample identity frameworks.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/inabajunmr/azidp4j/tree/main/azidp4j-spring-security-sample"&gt;with Spring Boot and Spring Security&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/inabajunmr/azidp4j/tree/main/azidp4j-httpserver-sample"&gt;with com.sun.net.httpserver.HTTPServer&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The approach helped my decision on interfaces. For example, when I considered whether the application with the library can implement client authentication or not, multiple implementations help my consideration.&lt;/p&gt;

&lt;p&gt;The library development with client implementations is better than just with test cases. Cases that I can't discover from the latter sometimes appeared.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I'm writing &lt;a href="https://github.com/inabajunmr/azidp4j"&gt;AzIdP4J&lt;/a&gt; that the library to build Authorization Server and Identity Provider in Java.&lt;br&gt;
The article talked about what I thought while developing.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/inabajunmr/azidp4j"&gt;inabajunmr/azidp4j: Library for Java OAuth 2.0 Authorization Server &amp;amp; OpenID Connect Identity Provider&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The library works as the following example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight java"&gt;&lt;code&gt;&lt;span class="c1"&gt;// convert HTTP Request query parameters to Map&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;authorizationRequestQueryParameterMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="nc"&gt;Map&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"scope"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"openid item:read"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"response_type"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"code"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"client_id"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"xyz-client"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"redirect_uri"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"https://client.example.com/callback"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"state"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"abc"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt;
                &lt;span class="s"&gt;"nonce"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"xyz"&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;authorizationRequest&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
        &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;AuthorizationRequest&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;
                &lt;span class="s"&gt;"inabajun"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// authenticated user subject. Application needs to implements user authentication. If no user is authenticated, specify null.&lt;/span&gt;
                &lt;span class="nc"&gt;Instant&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="o"&gt;().&lt;/span&gt;&lt;span class="na"&gt;getEpochSecond&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt;
                &lt;span class="nc"&gt;Set&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"openid"&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"item:read"&lt;/span&gt;&lt;span class="o"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// User consented scopes. Application needs to implements user consent.&lt;/span&gt;
                &lt;span class="n"&gt;authorizationRequestQueryParameterMap&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;azIdP&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;authorize&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;authzReq&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="c1"&gt;// Library returns what should do next so implements application's behavior.&lt;/span&gt;
&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;response&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;next&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;redirect&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Redirect to response.redirect.redirectTo&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;additionalPage&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Implements additional process like login or consent or...&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;errorPage&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Error happend but can't redirect to redirct_uri&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I hope your feedbacks. Thank you.&lt;/p&gt;

</description>
      <category>oauth2</category>
      <category>openidconnect</category>
      <category>oidc</category>
      <category>java</category>
    </item>
    <item>
      <title>The tool to find and edit any tool's config file</title>
      <dc:creator>inaba jun</dc:creator>
      <pubDate>Fri, 19 Mar 2021 14:12:34 +0000</pubDate>
      <link>https://dev.to/inabajunmr/the-tool-to-find-and-edit-any-tool-s-config-file-dd9</link>
      <guid>https://dev.to/inabajunmr/the-tool-to-find-and-edit-any-tool-s-config-file-dd9</guid>
      <description>&lt;p&gt;When I want to edit fish configuration file, I always google like "fish config" or "fish fishrc".&lt;/p&gt;

&lt;p&gt;But I made tool to solve it.&lt;/p&gt;

&lt;h1&gt;
  
  
  anyconf
&lt;/h1&gt;

&lt;p&gt;&lt;a href="https://github.com/inabajunmr/anyconf"&gt;https://github.com/inabajunmr/anyconf&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Behavior
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--23JlxLaR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/okr3gm5nha0n33icz4nh.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--23JlxLaR--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/okr3gm5nha0n33icz4nh.gif" alt="anyconf" width="574" height="370"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Recommended system requirements
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go version
go version go1.13.8 darwin/amd64
$ vim --version
VIM - Vi IMproved 8.1 (2018 May 18, compiled Jun  5 2020 21:30:37)
macOS version
$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.15.7
BuildVersion:   19H114
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Install
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;go get github.com/inabajunmr/anyconf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Usage
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;anyconf&lt;/code&gt; command shows supported tools like the following example.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ anyconf
? What's next key?  [Use arrows to move, enter to select, type to filter]
&amp;gt; fish
  screen
  git
  aws
  bash
  curl
  npm
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you can type and filter tools.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ anyconf
? What's next key? g  [Use arrows to move, enter to select, type to filter]
&amp;gt; git
  wget
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After selection, the configuration file open by vim. (vim is the default, you can change it via &lt;a href="https://www.notion.so/%5B%3Chttps://github.com/inabajunmr/anyconf#editor-configuration%3E%5D(%3Chttps://github.com/inabajunmr/anyconf#editor-configuration%3E)"&gt;anyconf configuration&lt;/a&gt;.)&lt;/p&gt;

&lt;h2&gt;
  
  
  Support new tools via Pull Request
&lt;/h2&gt;

&lt;p&gt;The mapping tools and configuration files are managed by the following file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/inabajunmr/anyconf/blob/main/static/configs.txt"&gt;https://github.com/inabajunmr/anyconf/blob/main/static/configs.txt&lt;/a&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight diff"&gt;&lt;code&gt;&lt;span class="p"&gt;anyconf ~/.anyconf/configs.txt
aws/config ~/.aws/config
aws/credentials ~/.aws/credentials
bash/bash_profile ~/.bash_profile
bash/bashrc ~/.bashrc
&lt;/span&gt;&lt;span class="gi"&gt;+NEWTOOL ~/.newtool.conf
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can send pull request if you want to apply NEWTOOL like this.&lt;br&gt;
After merging it, anyconf support NEWTOOL.&lt;/p&gt;
&lt;h2&gt;
  
  
  Support new tools via Local Configuration
&lt;/h2&gt;

&lt;p&gt;anyconf manages &lt;code&gt;.anyconf/configs.txt&lt;/code&gt; and you can support your tool via the configuration.&lt;/p&gt;

&lt;p&gt;If you put the following example to configuration, you can use NEWTOOL by anyconf.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;NEWTOOL ~/.newtool.conf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The configuration file can be opened via anyconf.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;I made &lt;a href="https://www.notion.so/%5B%3Chttps://github.com/inabajunmr/anyconf%3E%5D(%3Chttps://github.com/inabajunmr/anyconf%3E)"&gt;anyconf&lt;/a&gt; to find and edit any tools configuration.&lt;/p&gt;

&lt;p&gt;But it supports only a few tools that I use yet so If I receive Pull Request for other tools, I'll be glad. Thank you.&lt;/p&gt;

</description>
      <category>config</category>
      <category>tool</category>
    </item>
  </channel>
</rss>
