OpenID Connect Authentication

OpenID Connect (OIDC) is a simple identity layer added to the OAuth 2.0 to support single sign-on between two services. With OIDC, API clients can verify the identity of a user based on the authentication performed by an authorization server. It also provides basic profile information about the user in an interoperable, REST-like manner.

This section describes the steps required to configure OpenID Connect authentication. It also includes the following topics:

Configure OpenID Connect

Step 1. Go to Live > Products > {productName} | Edit > Integration | Edit Authentication. The Edit Authentication page opens.

Step 2. From the drop-down list, select OpenID Connect. This establishes OpenID Connect as the protocol used to authenticate users of your product, and opens additional fields that must be completed, as shown in the following image.


 

Step 3. Define the allowed OAuth 2 grants types for this product.  

  • Authorization Code—This grant type is mandatory and cannot be cleared.  AppDirect only supports the authorization code flow for single sign-on.
  • Refresh Token (optional)—When enabled, a refresh token is returned from the token endpoint, along with the original access and ID tokens. This refresh token can be used by the Developer to refresh the access token. The refresh token is valid for up to three weeks.

Step 4. Enter the redirect URL. This defines the OAuth 2 redirect URL where the authorization code is sent during SSO.  

Step 5. Configure the allowed scopes for this product. This defines what user information the API client can access.  

  • OpenID (required)— The minimum scope required for OpenID Connect. This cannot be unchecked. Note that if this is the only scope selected, the id_token and User Info endpoint will only contain the sub claim.
  • Basic Info (optional)—When enabled, email and profile scopes are allowed for this product. An access token with these scopes is returned and can be used at the /oauth2/userinfo endpoint to retrieve additional information about the user (for example, first/last name, email).  

Step 6. Configure the Initiate Login URL—Enter the URL in the Developer system where the user is redirected to initiate SSO.   

OpenID Connect is a service provider-initiated (SP-initiated) protocol. To learn more about third party-initiated login, see the OpenID specifications.

Note the following about this functionality:

When a user clicks on their MyApps tile, the marketplace issuer identifier is automatically sent as part of the request as a query parameter. Following is a sample issuer value as it could appear in this field:

<inititate_login_url>?iss=https://marketplace.exampletelco.com

In some cases a “target_link_uri” query parameter is also automatically sent in this request.  The value of this query parameter represents the location to which a user should be redirected after they successfully log in.  The italics text in the following shows an example of this:

<inititate_login_url>?iss=https://marketplace.exampletelco.com&target_link_uri=https://marketplace.exampletelco.com/deeplink

 

Step 7 (Optional) If the product is defined as importable when it is created, an Import Setup Form pane appears on the Edit Authentication page. The purpose of this form is to collect the information necessary to connect the application to the company when Company Administrators are importing an application. See Configure the Import Setup Form for information on how to configure this form.

OpenID Connect Relying Party (Developer) Configuration

AppDirect marketplaces support the creation of OpenID Connect relying party configuration via the SUBSCRIPTION_ORDER event, similar to what is done with SAML.  

Note: A single OpenID Connect client configuration (including client ID and secret) is created for each marketplace to which a Developer's products are distributed.  This single client configuration is shared across all subscriptions in a given marketplace but returned for all SUBCRIPTION_ORDER events.  

The steps represented in the following flow chart are built on top of AppDirect’s standard Subscription Event Notification Flow. Steps 5-10 represent the new steps added to support OpenID Connect SSO. A description of each step appears below the image.

1. An event is triggered by a customer action (for example, application purchase).

2. AppDirect sends a subscription event notification to the application vendor (Developer). This event is uniquely identified by an event URL.  See also step 11.

3. The Developer validates the OAuth-signature on the request, and can then read the event URL from the parameters to send an HTTP GET request for more information about this specific subscription event.

4. AppDirect sends a JSON or XML response to the Developer.

5. The marketplace “baseUrl” sent in the SUBSCRIPTION_ORDER event is used to request the OpenID Connect provider metadata.  See Example A for SUBSCRIPTION_ORDER event.  Note: The metadata is located at <marketplace_base_url>/.well-known/openid-configuration.

6. Metadata is returned and is used to retrieve the issuer ID, endpoints, and signature verification certificates. See Example B—OIDC provider metadata.

7. The metadata contains a ‘jwks_uri’ parameter that points to the current set of signature verification certificates for that marketplace.  Use this URL to request the current set of certificates.  

8. Signature verification certificates are returned (See Signature verification and key rotation to learn more, and see Example C—Signature verification certificates for an example response).

9. The OpenID Connect client configuration is requested from the “oidcClient” endpoint included in the SUBSCRIPTION_ORDER event.  This request is protected by the same OAuth key used in step 3.  See Example A on the OpenID Connect authentication event examples page) for SUBSCRIPTION_ORDER event.

10. The OpenID Connect client configuration is returned (see Example D—OIDC client configuration.  

11. The Developer responds to the original event notification (step 2), passing account and/or status information.

12. This status information is used by AppDirect to provide feedback to the customer via the AppDirect UI.

 

SSO flow for web server applications

This section describes the OpenID Connect SSO flow for traditional server applications integrated with an AppDirect-powered marketplace. A description of each step follows the image.

 

1. The user initiates SSO by clicking on the MyApps tile

2. The user is redirected to the previously registered Initiate Login URL to initiate SSO at the Developer. Following is an example:.

https://www.isv.com/oidc/login?iss=https://marketplace.exampletelco.com

3. The Developer initiates SSO by sending a request to the authorization endpoint. Following is an example of how it appears:

https://marketplace.exampletelco.com/oauth2/authorize?response_type=code&scope=openid profile email&client_id=s6BhdRkqt3&state=af0ifjsldkj&redirect_uri=https://www.isv.com/callback

4. The user is authenticated with the marketplace.

5. An authorization code is returned to the redirect_uri passed in step 3.  Note: this URI must also match the value entered in the Redirect URL configuration field on the  Edit Authentication page. Following is an example:

https://www.isv.com/callback?code=SplxlOBeZQQYbYS6WxSbIA&state=af0ifjsldkj

6. The Developer sends a POST request to the token endpoint to exchange the authorization code for the ID and access tokens. This request must be authenticated (basic authentication) using the client ID and secret.  

curl -X POST -u appdirect-49:9vY0s4yb2pbnP7Vz "https://marketplace.exampletelco.com/oauth2/token?grant_type=authorization_code&code=AYo3IQ&redirect_uri=https%3A%2F%2Fwww.isv.com%2Fcallback"

7. The ID, access and the refresh tokens are returned in the response (see Example E—Token response).

8. The ID token is validated by the Developer, including the signature. See Signature verification and key rotation to learn more and see the OpenID Connect specifications for details on token validation.  

9. The Developer retrieves additional user data (first/last name, email, etc.) from the User Info endpoint.  This is a regular API call that requires the access token returned in step 7 to be included as a bearer token.

curl -H 'Authorization: Bearer <access_token>' https://marketplace.exampletelco.com/oauth2/userinfo

10. The user data is returned

11. The user is logged in to the Developer application.

SSO flow for native applications

This topic describes the single sign-on (SSO) flow for native applications, such as mobile applications. For information on the SSO flow for web-server applications, see SSO flow for web server applications.

Special security considerations apply to native applications when using the authorization code flow. RFC 8252 - OAuth 2.0 for Native Apps was created to define best practices for such cases. These best practices include RFC 7636 - Proof Key for Code Exchange by OAuth Public Clients (PKCE), an extension to the core OAuth 2.0 specification that secures the authorization code flow when used in native applications.

AppDirect conforms to both RFC 8252 and RFC 7636.

AppDirect recommends the use of AppAuth client SDK to simplify integration with native applications and ensure best practices are followed.

This section describes the OpenID Connect SSO flow for native applications integrated with an AppDirect-powered marketplace. A description of each step follows the image.

  1. The user begins the single sign-on (SSO) transaction within the native application by, for example, entering their username and clicking on a login button.

  2. The Developer generates a cryptographically random code_verifier and associated code_challenge:

     

    code_challenge = BASE64URL-ENCODE(SHA256(ASCII(code_verifier)))

    Next, the Developer looks up the user’s OIDC configuration, opens a browser, and initiates SSO by sending a request to the authorization endpoint and including the code_challenge_method and code_challenge query parameters (required for PKCE). Following is an example of how it appears:

    https://marketplace.exampletelco.com/oauth2/authorize?response_type=code 
    	&scope=openid profile email
    	&client_id=s6BhdRkqt3&state=af0ifjsldkj
    	&code_challenge_method=S256
    	&code_challenge=FULBvRhW7stRYdJC2WQ1Tar4QtmoKtArNR6H-cnAGXg
    	&redirect_uri=com.isv.mobileapp:/callback
  3. The user is authenticated with the marketplace.
  4. An authorization code is returned to the redirect_uri passed in step 2. Note: this URI must also match one of the values entered in the Redirect URL configuration field on the Edit Authentication page. Following is an example:

    com.isv.mobileapp:/callback?code=SplxlOBeZQQYbYS6WxSbIA&state=af0ifjsldkj5 
  5. The Developer sends a POST request to the token endpoint to exchange the authorization code for the ID and access tokens. The request includes the code_verifier generated in step 2.

    curl -X POST "https://marketplace.exampletelco.com/oauth2/token?grant_type=authorization_code&code=AYo3IQ&&code_verifier=rtDJlZb3hnHD0P65DYiUF0Xmplzg_anBoflHNGq0yCM&redirect_uri=com.isv.mobileapp:/callback"
  6. The AppDirect authorization server transforms the code_verifier using the following method:

    BASE64URL-ENCODE(SHA256(ASCII(code_verifier))) = transformed_code_verifier

    The authorization server then authenticates the request by ensuring the transformed_code_verifier matches the code_challenge passed in step 2. After the request is verified, the ID, access and refresh tokens are returned in the response (see Token Response Example E in the Open ID Connect authentication event examples topic).

  7. The ID token is validated by the Developer, including the signature. See Signature verification and key rotation to learn more and see the OpenID Connect specifications for details on token validation.
  8. The Developer retrieves additional user data (first/last name, email, etc.) from the User Info endpoint. This is a regular API call that requires the access token returned in step 6 to be included as a bearer token.

    curl -H 'Authorization: Bearer <access_token>' https://marketplace.exampletelco.com/oauth2/userinfo 
  9. The user data is returned
  10. The user is logged in to the Developer application.

Signature verification and key rotation

The OpenID Connect specification provides guidance on how to effectively rotate asymmetric keys used for token signing.  AppDirect marketplaces have adopted the approach described in the specifications.

Each marketplace-issued id_token will contain a key identifier (kid) in the header of the id_token (JWT) that references the key used to sign the token. Following is an example:

{"kid":"1ee4d9e7dcfef215d133c7ed7ac87c95f8d8e712","alg":"RS256"}

This key can be used to look up the signature verification certificate that was originally retrieved from the “jwks_uri” endpoint in the  OpenID Connect provider metadata. See Example B— IDC provider metadata.   

Marketplaces have three or more active signing certificates at any given moment that are selected at random to sign tokens.  Since each key has an expiry date, OpenID Connect clients must be designed to make use of the kid value when verifying tokens and be able to detect unknown kid values to retrieve new keys when needed.  

This section explains how to configure integration for the two authentication protocols that the AppDirect platform supports for single sign-on (SSO): SAML and OpenID.

AppDirect supports SSO with SAML 1.0, 1.1, or 2.0, or OpenID 2.0, authentication. However, AppDirect strongly recommends that you use SAML because OpenID 2.0 is deprecated by many vendors (for example, Google).

To access the Edit Authentication page for both options, go to Manage > Billing and Distribution Products > {productName} | Edit > Integration | Edit Authentication.

Forced authentication for service provider-initiated SSO flows

Developers can modify the SSO integration for their application to always require users to re-authenticate during OP-initiated SSO flows.   

This optional feature can be adopted by Developers who require that an end user be explicitly authenticated (by entering a username and password) every time the Developer sends an authentication request to an AppDirect-powered marketplace.  For example, to be compliant with the Health Insurance Portability and Accountability Act (HIPAA), Developers may rely on forced authentication to ensure a higher degree of security for their SSO integrations.

Developers can choose to require that a user re-authenticate by including the “prompt” query parameter in the request sent to the authorization endpoint. If the parameter is detected by the marketplace receiving the request and contains the value “login” then the user is required to re-authenticate, even if an active session is detected.

The following is an example of the prompt query parameter included in the authorization request:

https://marketplace.exampletelco.com/oauth2/authorize?response_type=code
  &scope=openid profile email
  &client_id=s6BhdRkqt3
  &state=af0ifjsldkj
  &prompt=login
  &redirect_uri=https://www.isv.com/callback

Open ID Connect authentication event examples

Following are examples of various steps required to configure OpenID Connect as the authentication method for  your product. These examples are referenced on the Edit authentication page.

Example A—SUBSCRIPTION_ORDER event

{
"type": "SUBSCRIPTION_ORDER",
"marketplace": {

   "partner": "APPDIRECT",

   "baseUrl": "https://marketplace.exampletelco.com"

 },

...

 "links": [

   {

     "rel": "oidcClient",

     "href": "https://marketplace.exampletelco.com/api/developer/v2/applications/3448/oidc"

   }

 ]

}

 

Example B— OIDC provider metadata

{

"issuer": "https://marketplace.exampletelco.com",

"authorization_endpoint": "https://marketplace.exampletelco.com/oauth2/authorize",

"token_endpoint": "https://marketplace.exampletelco.com/oauth2/token",

"userinfo_endpoint": "https://marketplace.exampletelco.com/oauth2/userinfo",

"jwks_uri": "https://marketplace.exampletelco.com/oauth2/certs",

"response_types_supported": [

 "code",

],

"subject_types_supported": [

 "public"

],

"id_token_signing_alg_values_supported": [

 "RS256"

],

"scopes_supported": [

 "openid",

 "email",

 "profile"

],

"token_endpoint_auth_methods_supported": [

 "client_secret_basic"

],

"claims_supported": [

 "sub",

 "name",

 "family_name",

 "given_name",

 "email",

 "email_verified",

 "iss",

 "aud",

 "exp",

 "iat"

]

}

Example C—Signature verification certificates

{

"keys": [

 {

  "kty": "RSA",

  "alg": "RS256",

  "use": "sig",

  "kid": "431d667906c74df5cf5b48cefb5fb8acf7b2fc9b",

  "n": "wb36GVTnynuL6w_p9JM1jTqYWyeFcKMfiZmgdgXX_xMX5jermDeg9pabYpiv2JdMiHaX57qRydjx5C-zSVXnyKV-_TZ0HwA28-zGHWe9p8MqriO43qz9mp4uV8j5sNhWXzlzH72Z4CELl5-C4NdZcXhNmf_c9OBwhVn6a-qw0DtlHdVjlc71fex21HGimG1pybIFCrv_s5M6DARAukWO-WGEaiNvifBrP9-XvejSB9gzLmb0SJ74PnL8xxQz-C2ZTR-pnemRdB294IPIMJMsV0hCA0VQpQ3EWpiGNhq1Qim6n-8gCQp6ahNUQE9chxzWhXQAs_qA-cRAC0_YySWiZw",

  "e": "AQAB"

 },

 {

  "kty": "RSA",

  "alg": "RS256",

  "use": "sig",

  "kid": "1ee4d9e7dcfef215d133c7ed7ac87c95f8d8e712",

  "n": "yl43JvU6o_HlE6npH4-h0GQt4Sf7p7OOymPdNfpISFprg3s6xVEGV5sOw9xU-FWx9pd9u7HabSY286Pv4pLsnuKy3F-M52RtPCV1B11pxn01DSI9C17QKO7XAAOHWED9pj43pHirGHz_eDkpfLAck7wof5Qi0eKQT2_B70WYCF3Yis_V8WI8zgcJo9qIh4bbZUGVkiLXDoNbgr6KkulE4qrRNErSzgLXQlPm3623tudeoP1U8umfbWdnWmtTS8UO-lhgkJc5HT45HJwXFiSyKFTOX7nB1Ou99ZHCngL-KGn5xmLKExAZiV57BkRTTcYo-9qg1SKNivnKWwUb6crHpw",

  "e": "AQAB"

 },

 {

  "kty": "RSA",

  "alg": "RS256",

  "use": "sig",

  "kid": "308f248756b5f6ee4dd4c5d80b55850997ffde7f",

  "n": "5I-4yApxPzlxsPdO3x5o671FvxjjDUNHQrK88vvLTUcxrPU3sGy13hy4Rca4d-MVcYl_Lo-M2SqKsQVHEIPPE-YFzUUjScM1_XZaOCxapbPBS0iwnF0VhwB1m8DOCJmgmbeWX9KjiFm8nHMmZ5CzRb_ksYk7RgHEXZ-36g9d0bU5pDBxfV2XAVqsL4bBOVhJuh_iw3giceohmIWDEESGNn9zEdxWAAPCFMJEAyrmMIyNVVoGussShp8R0MVwozfK0KyP4sWtcYZqvGSwuBn4gEahTWILnwfclh9YGG2wrjVP7N8BUzlVOIA3CRYx5VEH-x0iN_BDV-wXajowJcq0XQ",

  "e": "AQAB"

 }

]

}

 

Example D—OIDC client configuration

{

 "oidc_client": {

   "client_id": "s6BhdRkqt3",

   "client_secret": "cf136dc3c1fc93f31185e5885805d",

   "application_type": "web",

   "integration_type": "per_marketplace",

   "grant_types": ["authorization_code", "refresh_token"]
   "response_types": ["code"],

   "allowed_scopes": ["openid", "email", "profile"],

   "redirect_uris": [

       "https://www.isv.com/callback"

   ],

    "initiate_login_uri": "https://client.example.com/oidc/login",
    "client_secret_expires_at": 0,
    "client_id_issued_at": "1577858400",
    "token_endpoint_auth_method": "client_secret_basic"

 }

}

 

Example E—Token response

 {

  "access_token": "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJzdXBlcnVzZXIrMUBhcHBkaXJlY3QuY29tIiwiYXVkIjpbIm9wZW5pZCIsImFjY291bnQiLCJiaWxsaW5nIiwiYXR0IiwibzM2NSIsIm1hcmtldHBsYWNlIiwiY2hhbm5lbCIsImhvc3RlZGNoZWNrb3V0IiwiaW50ZWdyYXRpb24iLCJyZXBvcnRpbmciLCJub3RpZmljYXRpb24iLCJQUk0iXSwiZXhwIjoxNDk4NjM3OTA4LCJqdGkiOiI0Y2FlMWY3Zi1lYzVjLTRlNzMtYWZlMC1mNGNkZmY1MTllYzAiLCJjbGllbnRfaWQiOiJsdHozWnI2R0VUIiwic2NvcGUiOlsiZW1haWwiLCJvcGVuaWQiLCJwcm9maWxlIl19.FGMCsVVd8Hswa_uHnKFFiD8rwl8WCVg7-KjLAdCRGHQ6oRdO4XLhyODO2uYGO2IXwz1gdX0QhRIDfXtyrxn4BF18yBR-R2sZ5DO7Eo7H8rWCJ5QF8u8bz5ToqW4L1y440FfBerauW77irwE68U-a7ZQerL5sKR5TzIFkqCOWUXAxX7J0XD--yJK0KVVFodbG0E0MtWzxEuq2Q2_kQHa-ioJ9CrmV6ayZ3vZSS_AaeE-cCjqu8mG1zPD6FPRxs4MXwE16Mgq-IlKpD5PrhTJ2cPCDDMWKTADKNUg77tKYJozgu4B3cM50Azw0euINevd7Hd6dw7s1fPyfKQaZvcZiLQ",

  "token_type": "bearer",

  "refresh_token": "

eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiJzdXBlcnVzZXIrMUBhcHBkaXJlY3QuY29tIiwiYXVkIjpbIm9wZW5pZCIsImFjY291bnQiLCJiaWxsaW5nIiwiYXR0IiwibzM2NSIsIm1hcmtldHBsYWNlIiwiY2hhbm5lbCIsImhvc3RlZGNoZWNrb3V0IiwiaW50ZWdyYXRpb24iLCJyZXBvcnRpbmciLCJub3RpZmljYXRpb24iLCJQUk0iXSwianRpIjoiOWMwMDAxODctYzYwZC00MzQ5LTg2NzItYTM4OTUzYTE1OTE3IiwiY2xpZW50X2lkIjoibHR6M1pyNkdFVCIsInNjb3BlIjpbImVtYWlsIiwib3BlbmlkIiwicHJvZmlsZSJdfQ.pMxQg8D6I-5C3_shman69vvfu5RExkwVmYxHbHhqHsoI9IKnI3JwqFPxYgJpWWkgVl_cKcgvm0k_YSrFiJa9__VIdPSkIOGDplJ_EUONB9akpEouFPZw5dsw7CLexRL9OPRo-QXOhnYLy6lS5G2gbvSapLTlz-McFRrhPosaAf8JmT8gGzTAP4Jpds6o4usLNC2j3UHHZBDj1u7m3qMUGwaPrPzDSPvb5mLM-0ZKCaLAttmXHMUZS-QA5anTc84Wdl6oCRfwNG5Mgy6-jQCmu1iDBkZhE9IMIqz5w-9m15evimGbFLvBAK0ehTtD9wDpkEtWU7WXCY5VvONFI_i29Q

",

  "expires_in": 3600,

  "scope": "openid email profile",

  "id_token": "eyJhbGciOiJSUzI1NiJ9.eyJzdWIiOiIyZjkzY2IyNC1mN2I5LTQzM2YtODc1ZS1iYjBkZDliMGYxYzEiLCJuYW1lIjoic3VwZXIgdXNlciIsImdpdmVuX25hbWUiOiJzdXBlciIsImZhbWlseV9uYW1lIjoidXNlciIsImVtYWlsIjoic3VwZXJ1c2VyKzFAYXBwZGlyZWN0LmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJpc3MiOiJodHRwczovL29kLXBrY2Y0Nnp3eS5vZDUuYXBwZGlyZWN0b25kZW1hbmQuY29tIiwiYXVkIjoibHR6M1pyNkdFVCIsImV4cCI6MTQ5ODU5ODMwOCwiaWF0IjoxNDk4NTk0NzA4fQ.Uwj6UqqNwAjT3qKYkmVt-VgqV5N0Vcql2w7JQOj4Qu-lXtMwXwWNF_uNOUTl9zvONjHw-Z0GpBI7rCA5rpuVYFVHoL6Ix23AF7g6ByWNn6AEjHwO5Yh1A4nS8ZULzlnEmuHBzIBMDKpOQROhGjfh_JpSpzMYDnrXCcFLVtHyebEu2f73oZwUAB_D0ucoPRgHmn2A3rKkVxWdZu5iKPDWKV-aDNw0ZicIR7dVLRUj-HQlwMp9zU4xpi169HInds10-jvaPzeEBj8KWAYfcRqcEAg-EafFCPUZK12NewM8apuaZJFEsL9g5Y6v5F48xOJ26k93DqHp4rTwy7OPEakyjQ"

 }