Pre-authorized Code Flow


The Curity Identity Server support for the pre-authorized code flow is experimental and should not be used in production scenarios. The described capabilities, configuration model, and associated behavior may change between releases of the Curity Identity Server in a way that is not backward compatible.

The Curity Identity Server supports the pre-authorized code flow, as defined by OpenID for Verifiable Credential Issuance (draft 11). This support is for experimentation and evaluation purposes, in the context of verifiable credential issuance, and should not yet be used in production scenarios. By default the pre-authorized code flow functionality is disabled. Run the Curity Identity Server with the se.curity.verifiable-credentials.enable system property set to true to enable it.

The pre-authorized code flow allows a client/wallet to perform a token request using a provided pre-authorized code and a user pin. The Credential Offer provides a standardized method for a client/wallet to obtaining such a pre-authorized code. With the help of the pre-authorized code, clients/wallets can request tokens without needing to perform authorization requests first.

The grant_type for this flow is urn:ietf:params:oauth:grant-type:pre-authorized_code and a token request using it must also include:

  • pre-authorized_code - The mandatory pre-authorized code, eventually received on a credential offer.
  • user_pin - The mandatory user pin, that the user received through out of band-mechanisms (e.g. displayed on a web page or received on an email or SMS message).


The OpenID for Verifiable Credential Issuance specification (draft 11) defines the user PIN usage as being optional. However the current support by the Curity Identity Server for the pre-authorized code flow makes it mandatory.

Current usage of the pre-authorized code flow requires the client/wallet using it to have the code capability.

Pre-authorized codes are not bound to clients. Any client with the code capability can perform a token request using a valid pre-authorized code. This behavior allows pre-authorized codes to be issued before knowing which client/wallet is going to use them.

Pre-authorized Code and User PIN Issuance

The OpenID for Verifiable Credential Issuance specification (draft 11) does not define how pre-authorized codes and user PINs are generated. This specification only defines how they are used when presenting credential offers to wallets and when requesting tokens on the token endpoint. Credential issuance systems, such as the Curity Identity Server, may provide APIs (Application Programming Interfaces) or endpoints that applications can use to obtain pre-authorized codes and user PINs. For example, an university portal can use these APIs or endpoints to fetch pre-authorized codes and create credential offers containing them (e.g. represented as QR codes). Currently, the Curity Identity Server allows the issuance of pre-authorized codes and user PINs on the token procedures of the following flows:

To achieve that goal, a script token procedure can use the getDefaultPreAuthorizedCodeData and getPreAuthorizedCodeIssuer functions, as illustrated in the following example

Listing 172 Script token procedure issuing pre-authorized codes and associated user PINs.
  function result(context) {

      // Get the default data to be associated to the pre-authorized code
      var preAuthorizeCodeData = context.getDefaultPreAuthorizedCodeData()

      // Change its expiration to be 10 minutes
      preAuthorizeCodeData.expires = preAuthorizeCodeData.created + 600

      // Issue both the pre-authorized code and the user PIN
      var preAuthorizedCodeIssueResult = context.preAuthorizedCodeIssuer.issue(
      // Response will contain the following fields
      return {
          "pre-authorized_code_expires_in": secondsUntil(preAuthorizeCodeData.expires),
          "pre-authorized_code": preAuthorizedCodeIssueResult.preAuthorizedCode,
          "user_pin": preAuthorizedCodeIssueResult.userPin


Currently, this functionality is only available on script token procedures and isn’t yet available on token procedure plugins.