URI Template in OpenID Connect Provider Configuration Response

OpenID Connect Provider Configuration Response for example.com can be obtained from

https://example.com/issuer1/.well-known/openid-configuration

This is a JSON file such as

{
 "authorization_endpoint":
   "https://server.example.com/connect/authorize",
 "issuer":
   "https://server.example.com",
 "token_endpoint":
   "https://server.example.com/connect/token",
 "token_endpoint_auth_types_supported":
   ["client_secret_basic", "private_key_jwt"],
 "userinfo_endpoint":
   "https://server.example.com/connect/user",
 "refresh_session_endpoint":
   "https://server.example.com/connect/refresh_session",
 "end_session_endpoint":
   "https://server.example.com/connect/end_session",
 "jwk_url":
   "https://server.example.com/jwk.json",
 "registration_endpoint":
   "https://server.example.com/connect/register",
 "scopes_supported":
   ["openid", "profile", "email", "address", "phone"],
 "response_types_supported":
   ["code", "code id_token", "token id_token"],
 "acrs_supported":
   ["1","2","http://id.incommon.org/assurance/bronze"],
 "user_id_types_supported":
   ["public", "pairwise"],
 "userinfo_algs_supported":
   ["HS256", "RS256", "A128CBC", "A128KW", "RSA1_5"],
 "id_token_algs_supported":
   ["HS256", "RS256", "A128CBC", "A128KW", "RSA1_5"],
 "request_object_algs_supported":
   ["HS256", "RS256", "A128CBC", "A128KW", "RSA1_5"]
 }

Fig. 1 OpenID Connect Server Configuration Response

This is simple and sweet, but it does not tell what optional parameters can be sent to each endpoints. You would have to look into the developer documentation for each services, and this will limit the scalability of the client implementation severely when you want to use optional features.

This could be alleviated by using URI template (RFC6570) in the configuration file.

To explain it, Let us just take a small portion of the above example:

{
 "authorization_endpoint":
   "https://server.example.com/connect/authorize",
 "token_endpoint":
   "https://server.example.com/connect/token"
}

Fig. 2 Excerpts of OpenID Connect Server Configuration Response

This can actually be extended through URI template like (line wraps are for display purposes only):

{
 "authorization_endpoint":
   "https://server.example.com/connect/authorize{?scope,response_type,  
    client_id, redirect_url, state, display, prompt, id_token, 
    login_hint, request, requests_uri}",
 "token_endpoint":
  "https://server.example.com/connect/token{?grant_type, 
   code,redirect_uri,client_id}"
}

Fig. 3 URI Templated version of Fig.2

This pretty much explains what needs to be sent to each end points.

HAL and JSON Schema Versions

In HAL, this will become something like:

{
 "_links":{
    "authorization_endpoint":{
      "href":"https://server.example.com/connect/authorize{?scope,
         response_type,client_id,redirect_url,state,display,prompt, 
         id_token,login_hint,request,requests_uri}",
      "templated":true
     },
     "token_endpoint":{
       "href":"https://server.example.com/connect/token{?grant_type, 
        code,redirect_uri,client_id}",
      "templated":true
     }
   }
}

Fig. 4 Server Configuration Response in HAL format

and in JSON Schema,

{
 "$schema":"https://example.com/openid-connect-schema",
 "links":[
    {
      "rel":"authorization_endpoint",
      "href":"https://server.example.com/connect/authorize{?scope,  
         response_type,client_id,redirect_url,state,display,prompt, 
         id_token,login_hint,request,requests_uri}"
    },
    {
      "rel":"token_endpoint",
      "href":"https://server.example.com/connect/token{?grant_type, 
        code,redirect_uri,client_id}"
    }
  ]
}

Fig. 5 Server Configuration Response in JSON Schema format

This way, the client can learn what parameter should be sent to the authorization endpoint and token endpoint respectively as well.

Note: Value of $schema is bogus for the time being. It should be the URL that returns the JSON Schema for OpenID Connect Messages 1.0. Value of $schema when retrieved should have something like:

{
  "description":"OpenID Connect Authorization Request",
  "type":"object",
  "properties":{
    "scope":{
      "required":true,
      "type":"string",
      "description":"space delimited array of the desired items",
      "items":["openid","profile","email","address","phone"]
    }
    "response_type":{
      "required":true,
      "type":"string",
      "enum":["code","token","code token","code id_token",
              "token id_token","code token id_token"],
      "description":"states what response should be returned"
    },
    "client_id":{
      "required":true,
      "type":"string",
      "description":"a string that identifies the client"
    },
    "redirect_url":{
      "required":true,
      "type":"string",
      "format":"uri",
      "description":"the url to which the response should be returned"
    },
    "state":{
      "type":"string",
      "description":"the string to be returned as-is in the response"
    },
    "display":{
      "type":"string",
      "enum":["page","popup","touch","wap"],
      "description":"An ASCII string value that specifies 
            how the Authorization Server displays the 
            authentication and consent user interface pages 
            to the End-User."
    },
    "prompt":{
      "type":"string",
      "enum":["none","login","consent","select_account"],
      "description":"A space delimited, case sensitive list of 
            ASCII string values that specifies whether 
            the Authorization Server prompts the End-User 
            for reauthentication and consent. "
    },
    "id_token":{
      "type":"string",
      "description":"An ID Token passed to the Authorization 
            server as a hint about the user's current or past 
            authenticated session with the client. This SHOULD 
            be present if prompt=none is sent."
    },
    "request":{
      "type":"string",
      "format":"JWT",
      "description":"An OpenID Request Object value."
    },
    "request_uri":{
      "type":"string",
      "format":"uri",
      "description":"A URL that points to an OpenID Request Object. 
             This is used to pass an OpenID Request Object by reference."
    },
    "login_hint":{
      "type":"string",
      "format":"email"
    }
  }
}

Fig.6 Describing parameters in JSON Schema

etc.

Expressing supported scopes and response types in JSON Schema

In the current draft, the supported scopes and response types are expressed through the configuration file like:

"scopes_supported":
   ["openid", "profile", "email", "address", "phone"],
 "response_types_supported":
   ["code", "code id_token", "token id_token"],
Fig. 7 Supported scope and response_type in OpenID Connect server configuration response
This can be expressed together with parameter definition through JSON Schema as:
{
  "description":"OpenID Connect Authorization Request",
  "type":"object",
  "properties":{
    "scope":{
      "required":true,
      "type":"string",
      "description":"space delimited array of the desired items",
      "items":["openid","profile","email","address","phone"]
    }
    "response_type":{
      "required":true,
      "type":"string",
      "enum":["code","code id_token","token id_token"],
      "description":"states what response should be returned"
    }
  }
}

Fig.8 JSON Schema version of Fig.7

The reason OpenID Connect server configuration file is using a flat “parameter_name”:”value” format is that there has been a fairly strong feeling among the developers that this kind of simplicity is important for them. So, we have decided to go with the flat name space over a year ago. Never-the-less, I still feel some appeal in the JSON Schema version of them.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.