Response SSO Vendor Documentation

Version 1.2.11

Introduction

This is the documentation for the Response OpenID SSO Provider (IdP). This is used for Single Sign On (SSO) within Response and its partners. This document is primarily for vendors that will integrate with this provider.

This is a Single Sign On (SSO) Identity Provider which is based on the Microsoft IdentityServer3 framework. IdentityServer3 is built upon OpenID Connect framework. The OpenId Connect specification can be found here: http://openid.net/specs/openid-connect-core-1_0.html#Authentication. The OpenId Connect is not to be confused with the OpenID protocol. The OpenID Connect is built on top of OAuth 2.0 protocol. It enables Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server, as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner.

Read about JWTs if you havent already. JWT is used to create the access tokens. You can test your JWT tokens by pasting into this online tool: https://jwt.io/

Why use IdentityServer3 implementation? Our original SSO used IdentityServer3, so this SSO project makes it backward compatible for our existing clients. This implementation is only a scaled down version of the original IdentityServer3 framework.

Getting Started

Registration

For first time vendors, you will need to communicate your interest in becoming a SSO client with Response. Once approved, the developers will register your client with this Identity Provider. You will be given tokens that will authenticate you to use our services. Once setup, you can begin to act as a client with the Response SSO Provider.

You must provide the Response team with the following information:

  • Name of your client project
  • All valid redirect_uri on successful login. For both staging and production environments

Response will return:

  • client_id
  • scope_id
  • secret value for calling the token api call (if needed)

Learning

You will need to get familiar with various technologies to help you understand how to use the system and what it all means.

Suggested reading:

  • Base64 - Encodes and decodes strings in base 64.
  • JWTs - JSON Web Token. Encodes and decodes access tokens that you can verify with.
  • JWKS - JSON Web Key Set. Gives information about the JWT. This includes the public certificate you will use to verify the authenticity of a JWT access token.
  • OAuth2 - Protocol for authorization.
  • OpenID Connect - Protocol built on top of OAuth2 that allows clients to verify their tokens.
  • IdentityServer3 - An OpenID Connect framework built by Microsoft.

Usage

This Provider project only supports the calls required by our clients (vendors). Supported functionality:

authorize

This is a login.

It supports the authorize endpoint. Official specs are here.

The client will provide a login link for their users that will direct them to this sso_provider. It will prompt them for a username and password if they have not already logged in. The username and password is from the Customer Credential table in our database. The following validations will occur:

  • client_id matches a supported client_id
  • redirect_url matches a supported redirect_uri
  • response_type can be one or more of ('token', 'id_token', 'code')
  • scope can be one or more of ('openid', 'email', 'phone', 'profile', 'address') plus your own assigned vendor scope
  • email and password are not blank
  • The is an existing Customer Credential (cc) record with the provided username (email)
  • The cc record is not locked
  • The cc record is registered
  • The password is correct

A client will call the authorize URL like this

GET (token)
https://id.response.com/connect/authorize?client_id={my_client_id}&redirect_uri={my_redirect_uri}&response_type=token&scope={my_client_scope}

GET (id_token)
https://id.response.com/connect/authorize?client_id={my_client_id}&redirect_uri={my_redirect_uri}&response_type=id_token&scope={my_client_scope}&nonce={random value}

GET (code)
https://id.response.com/connect/authorize?client_id={my_client_id}&redirect_uri={my_redirect_uri}&response_type=code&scope={my_client_scope}
Request Params:
  • client_id - The client_id that was assigned to you.
  • redirect_uri - The URL this user will be redirected to on a successful login. The provider will reject any redirect_uri that are not known. The value should be URL encoded
  • response_type - can be one or more of ('token', 'id_token', 'code')
  • scope - can be one or more of ('openid', 'email', 'phone', 'profile', 'address') plus your own assigned vendor scope.
  • nonce - Some random value (required for id_token).
  • response_mode - If set to "form_post" it will POST to the redirect_URI.

Arrange with the Response team of a redirect_uri you wish a user to return to. If this redirect_uri changes, you will need to notify the Response team of the change. Any redirect_uri that is not in the known list will be rejected.

If authenticated correctly it will redirect the user to the given redirect_uri and with a JWT token. It will look something like this:

https://my_redirect_uri.com#access_token=44d2c5f9c959f408f9a754d33c8c47e2&id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyIzZGF5X29uZGVtYW5kIjp0cnVlLCJhdWQiOiJpdmVzdCIsImF1dGhfdGltZSI6MTUxMzk3NDgzNSwiY2xpZW50X2lkIjoiaXZlc3QiLCJkZGNfdW5saW1pdGVkIjp0cnVlLCJkZWFsX2Rlc2tfY29yZSI6dHJ1ZSwiZWNfZnVuZGluZyI6dHJ1ZSwiZWNfcHJldmlldyI6dHJ1ZSwiZWNfd3NfZGlhbW9uZCI6dHJ1ZSwiZW1haWwiOiJTU09URVNUQGdtYWlsLmNvbSIsImVtYWlsX3ZlcmlmaWVkIjp0cnVlLCJleHAiOjE1MTM5Nzg0MzUsImZhbWlseV9uYW1lIjoiV29vZHdhcmQiLCJmc19lbGl0ZSI6dHJ1ZSwiRlNfSG9tZVN0dWR5Ijp0cnVlLCJnaXZlbl9uYW1lIjoiRGVyZWsiLCJpYXQiOjE1MTM5NzQ4MzUsImlkcCI6IlJlc3BvbnNlIElkUCIsImlzcyI6Imh0dHA6Ly9sb2NhbGhvc3Q6MzAwMCIsIm15X21vbmV5X3Rvb2wiOnRydWUsIm5vbmNlIjoiYWJjMTIzIiwicmVhbF9wcm8iOnRydWUsInNjb3BlIjoiaXZlc3QiLCJTdHJhdF9XZWJpbmFycyI6dHJ1ZSwic3ViIjoiQzVBRENGOUEtMzVFMi1FNTExLTgwQzctMDAwRDNBMzA1QzA5IiwiVHJhZGVfdG9vbHMxIjp0cnVlfQ.ED1pa-1yh-XpLvd5HqEw6zuQ88WKDFnfzdHMep59l7bAmZcPOqAGLaLHzqT_tRPmCAbZ3FzyaozJgC4fJ_xlc_mphZ14D4przKJt_1yeAY_zb1HhYPRsS6ybOxRK2HkABnl4DdGZx_TrdUxOA4gbGu2ZH30Rc2-GafaEBh82AeotsQhZ2MUUVF0h8QBsFHoMzysljekS5HsumVV_WJuGgcVXx27xVsB36RkAeNfYx5h3c8r4SplYCRcfboMBSXLh00jrj5Gn1x5L_cRcELefyxKHe-y9PEE7D8XCj3AhNRLHO8iE77b4pIf3N8z1o8uKOEyrWkcRhBpdjvokG3R5FQ&token_type=Bearer&expires_in=3600&scope=ivest&nonce=abc123
Response Params:
  • access_token - (if response_type 'token') Access token used for authentication of other calls.
  • id_token - (if response_type 'id_token') JWT encoded token that should be verified by client.
  • token_type - Bearer
  • expires_in - Number of seconds before the token expires. The client should verify the token is within the expiration time
  • scope The scope that given in the initial request. Can be multiple scopes delimited by a space.
  • code (if response_type 'code') Code used for getting the token.

The client should verify the token using the certificate found on the jwks page.

The session will store the user's id, access_token. If the user has already logged in they will not be prompted with the username and password, they will be redirected immediately back to the give redirect_uri.

token

This token call follows this specification: https://identityserver.github.io/Documentation/docsv2/endpoints/token.html

The typical use case of this token call is for mobile phones. Rather than use this provider's login page which may not be mobile friendly, they ask the user for their credentials and pass their credentials to this token call in one go. It will return the access_token that can be used to access other calls such as userinfo.

This call supports the grant_type of password and authorization_code. This is a POST API call and will return JSON for both success and error.

A curl example:

PASSWORD:
curl -X POST https://id.response.com/connect/token -H 'authorization: Basic bXlfY2xpZW50X2lkOnNlY3JldA' -d "grant_type=password&scope={client_scope}&username={username}&password={password}”

AUTHORIZATION_CODE:
curl -X POST https://id.response.com/connect/token -H 'authorization: Basic bXlfY2xpZW50X2lkOnNlY3JldA' -d "grant_type=authorization_code&scope={client_scope}&code={authorize_code}”

Request Headers:
  • authorization - "Basic <token>" where the token is "client_id:client_secret" base64 encoded. The client secret is given to you by the Response team.
Request Params:
  • grant_type - "password" or "authorization_code"
  • scope - can be one or more of ('openid', 'email', 'phone', 'profile', 'address') plus your own assigned vendor scope.
  • username - (password) Customer Credential email value url encoded
  • password - (password) Customer Credential password
  • code - (authorization_code) Code from authorize call (code type)

The response will be a JSON string including the access token. For example:

{
  "access_token":"5740041819c24dbb97310fced119d73a","expires_in":3600,"token_type":"Bearer","id_token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyIzZGF5X29uZGVtYW5kIjp0cnVlLCJhbXIiOiJwYXNzd29yZCIsImF1ZCI6Iml2ZXN0IiwiYXV0aF90aW1lIjoxNTEzOTc2NDk3LCJjbGllbnRfaWQiOiJpdmVzdCIsImRkY191bmxpbWl0ZWQiOnRydWUsImRlYWxfZGVza19jb3JlIjp0cnVlLCJlY19mdW5kaW5nIjp0cnVlLCJlY19wcmV2aWV3Ijp0cnVlLCJlY193c19kaWFtb25kIjp0cnVlLCJlbWFpbCI6IlNTT1RFU1RAZ21haWwuY29tIiwiZW1haWxfdmVyaWZpZWQiOnRydWUsImV4cCI6MTUxMzk4MDA5NywiZmFtaWx5X25hbWUiOiJXb29kd2FyZCIsImZzX2VsaXRlIjp0cnVlLCJGU19Ib21lU3R1ZHkiOnRydWUsImdpdmVuX25hbWUiOiJEZXJlayIsImlhdCI6MTUxMzk3NjQ5NywiaWRwIjoiUmVzcG9uc2UgSWRQIiwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDozMDAwIiwibXlfbW9uZXlfdG9vbCI6dHJ1ZSwicmVhbF9wcm8iOnRydWUsInNjb3BlIjoiaXZlc3QiLCJTdHJhdF9XZWJpbmFycyI6dHJ1ZSwic3ViIjoiQzVBRENGOUEtMzVFMi1FNTExLTgwQzctMDAwRDNBMzA1QzA5IiwiVHJhZGVfdG9vbHMxIjp0cnVlfQ.vooU0qmr3y94W6YxS83pq2dBWJxf7oPZvngmftgfHYlZfhqT8YTTai3SGktXpju3KB4k_BBqfYYBYLShHUDRB8E-M0dTeYeD1v1npNSNyYkEQ3L3R3-MA85zlB2gYG1-lsHGprGWCnRz7kdkloAT-s09ujeX3kodci-hrG6XMesVaHGEAUBu1lKszXjAXTGn_74-nOqMwXTH8edcy24UeXdmmISCKi7D8ITpjeNEDq8BdPIYSzRpWlQZ6nNTGvgF2PTpI08qQZlJMxba3GeSUCVIMKY-ddNJ8-7QHNhPucy9g9_0frJgK3sqTXq79sxsaTaVzrAZgH8Izt2-ag6J1Q"
}
Response Params:
  • access_token - Access token used for authentication of other calls
  • id_token - JWT encoded token that should be verified by client
  • token_type - Bearer
  • expires_in - Number of seconds before the token expires. The client should verify the token is within the expiration time

userinfo

This token call follows this specification: https://identityserver.github.io/Documentation/docsv2/endpoints/userinfo.html

You first need to get an access token using the token call or the authorize call. Once you have the access token you can get the user's information using this call. The access_token is stored in the session, so it must come from the same browser.

An example:

GET
Headers:
Authorization: Bearer {access_token}

https://id.response.com/connect/userinfo
The response is like an id_token payload response but unencrypted.

endsession

This is how the user can logout. This will remove their id from the session. There are no params.

GET
https://id.response.com/connect/endsession

They will be presented with the "Logout" page, then after 3 seconds they will be redirected to https://response.com/

Verifying Tokens

It is the responsibility of the client to verify the returned token with the public certificate. The certificate can be found on the jwks page.

jwks

The jwks page gives the client the public certificate to verify the access tokens. You can find the jwks page here https://id.response.com/.well-known/jwks.

This follows the standard JWKS format as outlined here https://auth0.com/docs/jwks.

The client really only needs the certificate which is the x5c value.

JWT tokens

You can use the online https://jwt.io/ tool to look inside a JWT token. For example in the authorize token given above you will see the following:
HEADER:
{
  "typ": "JWT",
  "alg": "RS256"
}

PAYLOAD:
{
  "3day_ondemand": true,
  "aud": "ivest",
  "auth_time": 1509053411,
  "client_id": "ivest",
  "ddc_unlimited": true,
  "deal_desk_core": true,
  "ec_funding": true,
  "ec_preview": true,
  "ec_ws_diamond": true,
  "email": "SSOTEST@gmail.com",
  "email_verified": true,
  "exp": 1509057011,
  "family_name": "Woodward",
  "fs_elite": true,
  "FS_HomeStudy": true,
  "given_name": "Derek",
  "iat": 1509053411,
  "idp": "Response IdP",
  "iss": "https://staging-id.response.com",
  "my_money_tool": true,
  "real_pro": true,
  "scope": "ivest",
  "Strat_Webinars": true,
  "sub": "C5ADCF9A-35E2-E511-80C7-000D3A305C09",
  "Trade_tools1": true
}

VERIFY SIGNATURE
RSASHA256(
  base64UrlEncode(header) + "." +
  base64UrlEncode(payload),

Public Key or Certificate. Enter it in plain text only if you want to verify a token
,

Private Key (RSA). Enter the it in plain text only if you want to generate a new token. The key never leaves your browser.

)

You can the extract the values you need in your own project. There are some set JWT token claim names returned, for example aud, iat, idp, iss, sub. You can learn more about the registered claim names in this spec.

The values most of interest to the client will be:

  • auth_time - The number of seconds since epoch when the authentication occurred
  • client_id - This should match your client_id
  • email - The email of the customer
  • email_verified - If true the email has been verified
  • exp - The number of seconds since epoch when this token should expire. Its up to the client to ensure the token is read within the expiration time.
  • family_name - User last name
  • given_name - User first name
  • iss - Should map to our SSO provider
  • scope - your client scope
  • sub - The User GUID (Customer Credential record in our database). We use this code to lookup users.

The non registered claim names is what the user is permitted to use. They are in the form "permission_code": true. For example the "deal_desk_core": true means the user is permitted to access the deal desk core package. Permission codes will only show true.

It is the responsibility of the Client to verify the authenticity of the access token. Use the certificate found in the JWKS page. Also check the token is within the expiration time. Check the token contains your client_id.

Openid Configuration

The configuration for the OpenID implementation can be seen here:

http://id.response.com/.well-known/openid-configuration

This supports Discovery and follows the standard openid-configuration format as outlined here https://openid.net/specs/openid-connect-discovery-1_0.html#ProviderConfig.

This page will show all the necessary endpoints and claims available for this provider.

Login process

Login

The user has registered and wants to login. The fill in their Customer Credential username and password. Once logged in they will be redirected back to the given redirect_uri.

Registration

A user must first register with the provider before they can login. They will be presented with a "Register" page where they must enter their Customer Credential email. Then they will be presented with the "Create your Password" page where they enter their password and confirm password. This will create a Customer Credential record in our database. Once registration is complete they will be logged in and redirected back to the clients given redirect_uri page.

The register page is found: https://id.response.com/register

Register also logs in the user and redirects them to the vendors page logged in. This means all the parameters used for authorize is also required for this register call.

Forgot Password

On the Login page the user can click the "Forgot Password" link.

They will be presented with the "Forgot Password" page where they can enter their Customer Credential email.

They have the option to enter their zip code, last 4 digits of their CC number (this looks at all payments they have made and gets the last 4 digits of each payment), the phone number.

If entered correctly they will be presented with the "Reset Password" page where they can change their Customer Credential Password.

They will finally be logged in and redirected back to the clients given redirect_uri page.