Browser SSO for CLI Applications
Command Line Applications are programs that you interact with entirely through your terminal and shell. They have no graphics or visual interface beyond what you see in your terminal after you run the program.
Well how you can use browser based Single Sign On for such an application ? The answer is OpenID connect with Authorization Grant flow..
Have you ever authenticated to Google Cloud Platform SDK ? Cellery SDK ? These CLI applications uses authorization code grant flow in order to authenticate to CLI applications. Well how do they do it ? What is the flow ?
In order to proceed with this story, you need to have a good understanding on how Authorization Grant work. Below is an abstraction of Authorization Grant flow.
If you don’t understand this don’t worry. The main thing I want to highlight here is Authorization Flow has a major part to be done with browser. You initiate the login flow from the browser, and get back an authorization code through browser to your client application and then your client application exchanges this authorization code with an access token. Since you are authenticating through browser, if you already have an authenticated session with IDP in the browser, you will seamlessly be authenticated with this approach.
Well the challenges you have are,
- from CLI you don’t have access to browser.
- Even if you access the browser somehow, how are we going to get the authorization code back to CLI code through browser ?.
Well, the first problem is something which we can address without much effort. ie you need to open up a browser and start authorization code grant type authentication. That is simply a GET request to the IDP with specific parameters which are defined in authorization code grant type. In order to open up a browser, you can either use a languages inbuilt functionality or a library depending on the language you used to implement SDK. Below is the snippet of code that we are using. This is implemented using GoLang.
Well, the first problem is solved. Next is “How are we going to get back to CLI once the authentication flow is ended ?” . If you pay attention to auth code grant type, the authorization code which the client application gets back upon successful authentication is sent via browser redirection. ie IDP does a redirection to the client application conveying what the authorization code is. If CLI can capture this browser redirection, the rest of the token flow can be continued through CLI application.
We have a simple solution for it, at the time of initiating the request opening up a browser, we start a localhost server which runs in the machine that CLI runs. This server is listening to a specific port and waiting until it gets back an authorization code.
When you try to authenticate to Google cloud through their SDK you will see the above in your terminal. This shows that you have initiated an authorization grant request and the important part is your redirect_uri. The redirect_uri is http://localhost:8085/ (URL decoded value) in the above request. This says, upon successful authentication redirect me back to my local server running along with CLI application with authorization code.
Until the authentication flow is ended and authorization code is returned back, the local server which CLI started waits and listens on that port. After successful authentication, the CLI will receive the authorization code through browser redirection and this can be exchanged with an access token. That’s it !!.
This is how it looks like.
Few things you need to keep in mind,
- Authorization server must be configured to have a redirect_uri with localhost(*). In authorization code grant, redirect URI which is sent in the initial request should be equal to the one configured in IDP.
- The authentication flow might have started in multiple terminals. Hence we can’t open the localhost server in a static port. First we have to check whether the port is occupied or not and then start the server on a specific port. We can search for different ports in a case if defaults are occupied. Depending on the port you open the server, you have to alter the redirect URI which you send out in the initial authorization request.
- We need to use an open client since we can’t embed Client Secret inside CLI application. Open Clients don’t have a client secret, simply having they only have a client ID. Also open clients don’t support Client Credentials grant type since there is no way to prove the client authenticity.
- In Cellery CLI application we have used WSO2 Identity Server which support all above features OOTB.