OpenID connect authentication using the authorization code flow

Hey folks,

I am in the process of implementing the OpenID Connect Flow in my application and have some questions. Taking into account the OpenID Connect principles and the existing implementation with laminas-api-tools/api-tools-oauth2, I have managed to get the corresponding response with an id_token.

If I have understood the authentication using the authorization code flow (Final: OpenID Connect Core 1.0 incorporating errata set 2) correctly, the auth server authenticates the requesting user by specifying the user name and the corresponding password, before responding with a code and / or id token.

Actually the laminas-api-tools/api-tools-oauth2 package allows the authorization code grant type, where the user has to consent the request. Since the consent is answered with “yes” the response will contain an auth code. With this code an access token can be requests.

So far so good.

Do I have to override the consent with my own implementation of a desired login?

The following lines in \Laminas\ApiTools\OAuth2\Controller\AuthController (198 - 204)

        $authorized = $request->request('authorized', false);
        if (empty($authorized)) {
            $clientId = $request->query('client_id', false);
            $view     = new ViewModel(['clientId' => $clientId]);
            return $view;

… allow only a consent and no user login. There is no real distinction between consent and login. So I assume that I have to implement this distinction myself, right? Or is there perhaps another solution that I can’t see at the moment?

Hi @ezkimo ,

  1. My dumb question would be why are you using API Tool when it will be discontinued in the future?
  2. The answer to your question will be it depends on you and what you want. If you’re a man of perfection then yes, you should give a thought to the correct response status and if not then you’re good to do as long as it works.
  3. According to the master of TDD he himself accepted in his book that you’re allowed to pass a test on a tight deadline and leave a todo or something like that remarks as a backlog that this issue needs to be fixed in the future even if that future never comes. The part in bold is my addition which I’ve found in my personal development experience. It doesn’t mean it is always the case.

So, the world is yours to walk upon. Thanks!


to answer your questions …

  1. A good question. I know that Api Tools are kinda outdated because it was said already, that it would be replaced or better said will be discontinued. On the other hand it feels still comfy for me. My last two customer projects were done with Api Tools. This one is a small private project I 'm trying some new approaches. On of these is the OpenID Connect flow.

  2. The implementation should be as good as possible so that it can be used in future projects. With OpenID Connect flow, it’s not just a matter of adjusting a status. Hence the question of whether there might be some kind of best practice or tips from people who have already implemented OpenID Connect.

  3. As there is no real deadline for this small private project, I will probably play through a few scenarios myself. As the OpenID Connect standard is final and very well described, I currently assume that I only need to extend the AuthController of the laminas-api-tools/api-tools-oauth2 package. At least that seems to me to be the most practicable way. But you’re right, of course. In case of doubt, I won’t be able to avoid a few todo notes in the source code.

Thanks for your answer. :wink:

Hi @ezkimo,

I hope it may be available on Git Hub as it would be good for me to look at. Thanks!

Hey there.

I have implemented Oauth2 and OpenID in my laminas projects (MVC), and ended up using the “league/oauth2” package (league/oauth2-client - Packagist)…

This was not too painful to do, so it is at least one possible way of doing it…

Hey @jAsgeir ,

thanks for your answer. I 've used the league/oauth2 package in the past to implement third party providers like Azure Active Directory, Microsoft and Google. My aim is the other side around. It 's all about creating an own OpenID / OAuth2 server instance, that you can handle with packages like league/oauth2.

Ah, I see.

I thought the consent always take place at the authorization provider, and not at the OAuth server? I mean the auth provider holds the protected info that is requested in the scope?

OpenID Connect extends OAuth2. The first send request is always an OAuth2 authorization request (RFC 6749). An application (client) requests the OAuth2 authorization endpoint to gain a token or a code (depends on what is defined in the response_type parameter).

OpenID extends RFC 6749 and adds a further response_type value id_token. This new value can be combined with the already known values token or code. The scope parameter with the value open_id is strictly required, because otherwhise it will be a standard RFC 6749 authorization flow code.

Response Type id_token code

A request with the response_type=id_token code parameter makes it pretty simple to gain information about the user and receiving an authorization code for the application (client). The following steps are done:

  1. Authorization code request like https://domain.tld/oauth/authorize?client_id=your-client&redirect_uri=your-redirect-uri&response_type=code id_token&scope=openid&state=123
    The code id_token value of the response_type parameter is essential. Together with the scope parameter, which is also essential it will force the server to redirect the request.
  2. The OAuth2 server takes the request and authenticates the given client. It redirects the user to a login prompt (Open ID defines some more prompts as well).
  3. The user enters his credentials and sends this credentials to the authorization code request.
  4. The OAuth2 server authenticates and authorizes the user by it 's given credentials and id token and authorization code are issued from the authorization endpoint.
  5. The received id token is a normal JWT token which contains some informations about the issuer and the user. The response contains also an authorization code, with which you can execute an OAuth2 token request to gain an access token for the given user.
  6. The OAuth2 server responds with access and refresh token for the given user so that every following resource request is authenticated and authorized by the sent acces token.

My intention is to extend the packages so that the described flow works smoothly. Currently, the API Tools can display an OIDC flow. However, this is only done via the consent prompt. A login prompt is not implemented.

Accordingly, I need an implementation of laminas\laminas-authentication and must extend the OAuth2 authorization controller of the oauth2/server package. The workflow must be designed in such a way that the redirect URI of the client is looped along until the ID token and the authorization code are issued. At the same time, the credentials must be specified in such a way that they are redirected back to the authorization controller after successful authentication.

When I am finished with the implementation, I will publish it here. I promise.
Then you can consume it with theleague/oauth2.