Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Page Tree Search
rootPageCognito Client Integration Guide

Login

USTA’s implementation of Cognito redirects the user to the Cognito Hosted Login Page (Cognito Native Login). When the user signs in for the first time, we employ a just in time migration strategy. Users are presented with the ability to Sign Up (create a new account) or Sign In with an existing account.

It is the responsibility of the Secure Client page to check if the user’s lightweight profile is completed. If it is not, the user will be redirected to the lightweight profile screen until the required fields are filled out and saved.

Note: Janrain has been deprecated as of 2022.

Expand
titleSign in Flow

 

Approach

Expand
titleStep 1: Obtain Client Id and Client Secret Keys

Before you begin the development of your browser-based application, contact USTA to discuss what data you will need to access from USTA.  Credentials will be issued for use to connect via HTTP.

Credentials:

  1. client id

  2. client secret

USTA Admin will register your application as a client in the Cognito configuration.

Expand
titleStep 2: Add link to Cognito Hosted Login

Add a link in the form of:

https://stage-account.usta.com /login?client_id=[your_client_id]&response_type=code&redirect_uri=[your_redirect_url]

When the token for the authorized customer is needed Client API application needs to follow typical OAuth 2.0 flow using authorization code grant type. To perform such flow Client API should be registered in the USTA authentication service and should have valid:

  • clientId - generated for every API Client during registration

  • secret - generated for every API Client during registration

  • callbackUri - an endpoint where authorization code will be passed after successful login - should be configured for all clients

  • state - a random generated value such as UUID to prevent CSRF attacks. ie '29ca0dd4-966d-400d-9abc-570568f5c339'

To perform login as a customer, API Client application should follow such steps:

  1. Client App redirect to login or authorize URLs:

    • https://stage-account.usta.com /oauth2/authorize - can be used if application should NOT ask the customer if they want to continue as a current, logged-in user (from SSO session) - user will be logged-in automatically if SSO session is in place with url parameters:

    • client_id={clientId} - mandatory, for example: 25idmdru0ucur4loa3hklcvpsa

    • response_type=code - mandatory

    • scope={requested scopes} - optional, if empty, all required scopes will be assigned to the token

    • state - a random generated value such as UUID to prevent CSRF attacks. ie '29ca0dd4-966d-400d-9abc-570568f5c339'

    • redirect_uri={callbackUri} - mandatory, for example:


    https://www.usta.com/idpresponse

    This occurs when the /login endpoint is called while an existing SSO session is currently active. In this case, the client is not challenged to reenter credentials. If they choose to Sign In as <XXXXXXX> then the session established from the prior login challenge will be used.

  2. After redirection customer can sign in or sign up using the email address and password or Facebook account:

Add Logic to Client Secure Landing Page

Expand
titleStep 3: Get Auth Code returned from the previous step

When valid credentials are provided then the browser is redirected to {callbackUri} with code={authorizationCode} param in the url

Expand
titleStep 4: Call to /token with Auth Code to obtain tokens (Access, Refresh)
  1. The {callbackUri} endpoint request should start obtaining the token process by calling POST: https://stage-account.usta.com /oauth2/token endpoint with such params (by x-www-form-urlencoded format):

    • client_id = {clientId}

    • redirect_uri = {redirectUri}

    • code = {authorizationCode}

    • grant_type = authorization_code

    and by passing API Client credentials by standard Basic Authentication header:
    Base64encoded: {clientId}:{secret}

    EXAMPLE:

    Code Block
    curl --location --request POST 'https://stage-account.usta.com/oauth2/token' \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --header 'Authorization: Basic M2hoMWpnNmRxNHR2N3R1cjR2ODk1dmFlazg6MXU3Y2NmNHBzcXAwdjcwamQwNm9tNnJvZm5tcHM2YnIzZmY1Y245M3ZjbGppaXVpMjBzZQ==' \
    --data-urlencode 'client_id=3hh1jg6dq4tv7tur4v895vaek8' \
    --data-urlencode 'redirect_uri=http://localhost:8000/logged_in.html' \
    --data-urlencode 'code=806aacd0-ead5-4973-8c2c-c8b68599fe2e' \
    --data-urlencode 'grant_type=authorization_code'
  2. As response 3 tokens will be returned in the JSON response:

    Code Block
    {
        "id_token": "eyJraWQiOiJCaVRJbkU4c1YzZDkyRnNhejFjS1FlckVIXC9OU3Y5a0YzY2FabWNSY3ZSdz0iLCJhbGciOiJSUzI1NiJ9.eyJhdF9oYXNoIjoiUTRkd0NRY2lqTXVaLUY1RXhaZFh3QSIsInVhaWQiOiIyMDE3MDA4MDA0Iiwic3ViIjoiYzVjZjRkNTUtOTFmYy00OWExLTkxY2ItOTY5NmFmY2NmODRkIiwiYXVkIjoiMjVpZG1kcnUwdWN1cjRsb2EzaGtsY3Zwc2EiLCJlbWFpbF92ZXJpZmllZCI6dHJ1ZSwidG9rZW5fdXNlIjoiaWQiLCJhdXRoX3RpbWUiOjE1ODQwMTQ4NjgsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC51cy1lYXN0LTEuYW1hem9uYXdzLmNvbVwvdXMtZWFzdC0xX0ZJekpWQnJsTCIsImNvZ25pdG86dXNlcm5hbWUiOiJjNWNmNGQ1NS05MWZjLTQ5YTEtOTFjYi05Njk2YWZjY2Y4NGQiLCJleHAiOjE1ODQwMTg0NjgsImlhdCI6MTU4NDAxNDg2OCwiZW1haWwiOiI2dXN0YUBjemVzLmlvIn0.Dz2m6hLMfbUlQp18VUyWoZpQKlp9X2x1hFqhpLi6hn3BrKawHu2NO_EPDbhiDif7WHBvmn-7nYmH_93WRwUyCD2ZkRNCs2sFTTBQD4NSOb66SHnhfKzsJjUmhzO86xiW1aTXZy0pu5MlsOojYOH9QayqJuefMWQkCQdAJ6ZPfFj1zkAYH8Uw8JlvITNtSEz--s3NeIYKfyloHIrh_ZVbo5ro-DskBjNqMu8Oc8k1be9BzTwXGWGPCdKucNpjyGTwp-QZKoL-gLTW-xXzQDSs2PVkftCGBZ9v1PJHwOOhUpVdBdpwg_9DgEcfZFSu5fsyH2mlhuM2DGikhMWokZ_P0w",
        "access_token": "eyJraWQiOiJCS3ViejVJeDhGOGNadHBJRTI4MjFqTkZFQlUzWGRYN29qdjNKWGV5RXpnPSIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiJjNWNmNGQ1NS05MWZjLTQ5YTEtOTFjYi05Njk2YWZjY2Y4NGQiLCJ0b2tlbl91c2UiOiJhY2Nlc3MiLCJzY29wZSI6ImFwaS1jdXN0b21lclwvY3VzdG9tZXI6dXBkYXRlIGFwaS1jdXN0b21lclwvY3VzdG9tZXIucHJvZ3JhbTpyZWFkIG9wZW5pZCBhcGktY29tbW9uXC9yZWZlcmVuY2UuZGF0YTpyZWFkIGFwaS1jdXN0b21lclwvcHJvdmlkZXI6cmVhZCBhcGktY3VzdG9tZXJcL2N1c3RvbWVyOnJlYWQiLCJhdXRoX3RpbWUiOjE1ODQwMTQ4NjgsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC51cy1lYXN0LTEuYW1hem9uYXdzLmNvbVwvdXMtZWFzdC0xX0ZJekpWQnJsTCIsImV4cCI6MTU4NDAxODQ2OCwiaWF0IjoxNTg0MDE0ODY4LCJ2ZXJzaW9uIjoyLCJqdGkiOiJlM2MxZDExYy04YWVhLTQ5ODgtODgwMS01YzE5YTY5NzcxZGYiLCJjbGllbnRfaWQiOiIyNWlkbWRydTB1Y3VyNGxvYTNoa2xjdnBzYSIsInVzZXJuYW1lIjoiYzVjZjRkNTUtOTFmYy00OWExLTkxY2ItOTY5NmFmY2NmODRkIn0.Jnz_zLPzBZUKbdOlJ1Md8GsV4k_IXofHpikpv5WcInxns16shJKYCmQEVnu1-lMh52o2i9XC1uLYw810MlLTW_fxWKzprBFDkVKwneMo_pvl_aZYmZlIsm8LU8DEtKlYeoV1iUMmxpK0t0Bbk7hdKAV7fo3RZU665CAP28wUHdyDbVQ_eWeX7Pkta6LprExs2h4FPJIb8nVTM6Ap55FgpjX3OtECTM5I6-t1CV4E8gRQpxGD-ocvwLE0wqqEMBM5YNJD-96mdG1cA74BzjmoctddJJkUOWXY67wK4rSbvgoiGZpA8Sk8xzkvblCWcREQLrPoAVRvXwNVFzFzbShK_w",
        "refresh_token": "eyJjdHkiOiJKV1QiLCJlbmMiOiJBMjU2R0NNIiwiYWxnIjoiUlNBLU9BRVAifQ.VAffDHiEbFD48twdqMUQh61g3KcDhVGcwDk7OdC1oDV9aw33lXd2DicJzaG3bvoUCZPDzBeLnviTstzy2QfwSU9TQm6puhYqN9ZhjucXU_H38KxgQvf1ZwXaN5by_ANcGL3QTV1DuTXjcUbTwKDo5sxIeYAyJ7pCtDTbY_zQjf8wXmFOzvAKCimoShLT7HgM10c3QPcGYn4WzyXtokMUoa8jJD85hoOLCyPFMO6lVSxTwfbhcDQwRBMHPVavElIfK-4XorMXnc-GQZIo2AlTo57wzL9U8LfZJuCgTNLxfY-glYhp9NkGExIFMdGk0JgEzUv_TFcVCwG_6T8qoKRt5Q.s4L63XHYqKPYpxi1._TTxH91aJ5Xjxuo_RzKHzKaPdb2yOf9BhAwcnShr49ZnKLNiOwUUXW1ZAJtLUZE1wdiQ8dBN5dXxXh-AZqJwD0VaQmPVVIVT6Bhib8npQQMed6ErWqg0UA1od3yrSRWeQL_gRX_IiDBKYW0fkf-TbC6on646_8R-dzNpqkbxa8m4rDYG-tA0bU44sNY1nrxsHsO4sCtI1ZVkIhf2CZrjrQ-xJRl0jXbRNCDUSlNLtkh3esBbGQuLZDLFBZUnZMXYx6Sg3LwHb06-n9BKCakA9x0wBrsOaoV8zfklfHbZwulRvFOtcxsHZGHqyMbOnlAEu11QC7_dQ_HAOXKjtgWZ_M1RdUqDtoWSV9ueEpMdCVtJGlqKqnOEMKDEfdSeu2Q8kkPf2hHJOKzcihph0ym4f-B_CHFQNsh9oR5-f_-Ck7xKLm433BON_Vkz0U3_kTFb1-LSbYBECS0-5t6Pd2sxocFHYNpblqD6bddYA1pqFDHfLXxLUL6EID0BkzMeV9H97f4Vv4MAkZ3XnvGKvrPqYbA63fjs83K59IKLc8vFTh-EjU5VB9B5YJlfoCOzk1bt4cS9iJQVDvTvKeTie_QQ7f43k2HkkgpqG3sI6wKcgnZFeNNhnPB8R4YLf6rdNvcND4YXgo3lsU5-6xVD1orKbTNyxz_sy3roF4AESfyYTiGKbtTe8SJ1cT3hajs27go-85EHK4lZPPmrnV_WTX8YLkmWcy6OWnTva6ADxeOfqyfnX7IHy14q6mPG5PkcZ_NProCC_XiXgMAWpneQe1HuAtOFYgP-D2_jeR_2daxYji8t1AfxKlEjbATaSRyOyac3Qq9qBcGfPmu36kDWbUdfPG5AKRV88-co_gVEimbCiPJ9fOe5SNpoqSr0af3TeaffM5O3GQryXn5Zn_-pHKs4U6U3NLvxw4Bh2Wkj7VfaoUk5AozHjtWwn8xY6gvvFgVcMBpkmsAbv2BYsxxtkrh8DPF7VANY6wnILp18uryHWSBCLS-fXXdkxScdtTs2t6voa1asg95IIvP1R7Ih6H0DvaTZSz1FXNvq1CsaQ_geFrYsd_muf2bkM15lcvqsRKJE_ej5CewLr22yXDkczADRN0giSCuswo5-RMwHdIopXh9PfGClZ7Y_i-qFyXLKhw7RC_3RESMcIsH1t_rnj35aC3vmGX7X-IbprUiFFgtQVPLUZZc030z7cTzt49xmJsiiJ41LuUD7V6706ysT8tTCKmkZy8XsTovTFoEyIpMNJMLgrIEzGuSIrlSLqtR67XUAQk7FlE-m3v7_dC0V2b19gBrc4hoZJmD3rPz2LBLgdwXyJrGBFr3M3depeaXNhld-H-1eYRmTVhktDSNZ_v8ML_9SKHaE9xW00Xy0qaOm6_2nCNGUd6iXdJ49ntZ4gI1Wlhn5G0hbzBbeAylg26IMgHfphPCGJNTbCcP_WYI8yX-_fjb0rzPVx40kchyYkFZ45ey-bFmw9cIgmc85VJtp7y7OD26DdyE.IiVbf5rc480zvbISXeLm6A",
        "expires_in": 3600,
        "token_type": "Bearer"
    }

    id_token - JWT token with user identity information: valid for 1h:

    Code Block
    {
      "at_hash": "Q4dwCQcijMuZ-F5ExZdXwA",
      "uaid": "2017008004",
      "sub": "c5cf4d55-91fc-49a1-91cb-9696afccf84d",
      "aud": "25idmdru0ucur4loa3hklcvpsa",
      "email_verified": true,
      "token_use": "id",
      "auth_time": 1584014868,
      "iss": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_FIzJVBrlL",
      "cognito:username": "c5cf4d55-91fc-49a1-91cb-9696afccf84d",
      "exp": 1584018468,
      "iat": 1584014868,
      "email": "6usta@czes.io"
    }

    access_token - JWT token for accessing USTA APIs/services - valid for 1h:

    Code Block
    languagejson
    {
      "sub": "c5cf4d55-91fc-49a1-91cb-9696afccf84d",
      "token_use": "access",
      "scope": "api-customer/customer:update api-customer/customer.program:read openid api-common/reference.data:read api-customer/provider:read api-customer/customer:read",
      "auth_time": 1584014868,
      "iss": "https://cognito-idp.us-east-1.amazonaws.com/us-east-1_FIzJVBrlL",
      "exp": 1584018468,
      "iat": 1584014868,
      "version": 2,
      "jti": "e3c1d11c-8aea-4988-8801-5c19a69771df",
      "client_id": "25idmdru0ucur4loa3hklcvpsa",
      "username": "c5cf4d55-91fc-49a1-91cb-9696afccf84d"
    }

    refresh_token - special, log-life token for refreshing id and access tokens - valid for 30 days, cannot be refreshed

  3. Client endpoint should save tokens for future usage:
    id_token, access_token - can be saved in the secure browser space, for example, cookies, local storage and can be used for calling USTA APIs/services, should be never passed by URL params.
    refresh_token - can be saved on the server-side in session or other safe storage, must not be passed to the browser

USTA recommends naming cookies based on the client id. Cookies should also be stored on the subdomain level (i.e. subdomain.usta.com). Cookies should not be stored on http://usta.com domain as cookie collisions can occur and may be overwritten in unexpected ways.

Expand
titleStep 5: Check if Lightweight Registration was completed and there are no missing registration fields

Call /customers/me endpoint and check validation errors:

  • EXAMPLE:

    Code Block
    curl --request GET 'https://stage-services.usta.com/v1/customers/me/' \
    --header 'Content-Type: application/x-www-form-urlencoded' \
    --header 'Authorization: Bearer eyJraWQiOiJiQWhoTGRGQlpEV3B6YkNEaXVRcERKNDBCcmljbjNhdlRMM2w5TFp4QjNZPSIsImFsZyI6IlJTMjU2In0.eyJzdWIiOiI1ZGQzMDE0MS1mYzdiLTQ2MzctOGQyZS0wYTcwMTU3MmU4MmQiLCJ0b2tlbl91c2UiOiJhY2Nlc3MiLCJzY29wZSI6ImFwaS1jdXN0b21lclwvY3VzdG9tZXI6dXBkYXRlIG9wZW5pZCBhcGktY3VzdG9tZXJcL2N1c3RvbWVyOnJlYWQiLCJhdXRoX3RpbWUiOjE1ODA3NjcwMTUsImlzcyI6Imh0dHBzOlwvXC9jb2duaXRvLWlkcC51cy1lYXN0LTEuYW1hem9uYXdzLmNvbVwvdXMtZWFzdC0xX3FoWTNLWTdPTCIsImV4cCI6MTU4MDc3MDYxNSwiaWF0IjoxNTgwNzY3MDE2LCJ2ZXJzaW9uIjoyLCJqdGkiOiI4NzliYTNmYS04NzBlLTRiZGYtYjQ4NS0wMDg2ZTcxOTFjODgiLCJjbGllbnRfaWQiOiI1ZXY4YWk1M3Q1dXVkMXAyNDZya3MydjFkYiIsInVzZXJuYW1lIjoiNWRkMzAxNDEtZmM3Yi00NjM3LThkMmUtMGE3MDE1NzJlODJkIn0.h2FUNO0QPe0LXdI0PhsvpNMyjvo45pRUVlgFyYSS_muB718rsX8CIJnEj3pXyLyzEKBGF734u2uV-AtQZY1fRdsb6Hu2rPxzt7w6W8q2dUTO6E_TRHrQ5qD9m8GMnjhHJQvVcpC9S9uX6j2QwUBJ6qmEH4E4yVeVlTp_jgtv93H4fL2epcpTvXtAmLKvdtRDH0lMHxosGtfBKWbuglmQreROpt3Jq8hJ0cD__13EtbT_XFNzyIwCkqMmma8o_xLDnvzxcl7ozIEgBm_vrGzY2VWWvpTWak0g9JXlKUeZQLHck8alOFYygE-_NijHWSyrTyzSaTXu4UzIOc97K5ckxQ'
  • Check Validation Errors. If you get the following errorCode, then you will need to perform Step 6.

  • Code Block
    {
        "errors": [
            {
                "errorCode": 400613,
                "message": "Customer profile is not linked"
            }
        ]
    }
  • In the response payload, check to see that required lightweight registration fields are returned. If any of the required fields are missing (i.e. DOB), you will need to perform Step 6.

Expand
titleStep 6: Redirect to Lightweight Profile Registration Page if Hybris Profile does not exist or incomplete LW profile

Customers can create a USTA profile there, by filling-out basic, mandatory data. When a customer clicks the “Register” button and all data is valid then the browser is redirected back to the passed redirectUri and access_token can be used against services.

Working with JWT Tokens

JWT tokens are encrypted JSON format and contain fields called claims. Once you generate an Access Token, you can examine the contents at http://jwt.io . This is a valuable debugging tool.

Dont Make the User Type In Credentials Again

With OAuth2 application developers often make the mistake of retrieving an Access Token before each API call. This is not efficient. Instead, use the long lived Refresh Token that is supplied with the short-lived Access Token when the Authentication Code is exchanged for the Access Token. Use the Refresh Token to rerequest another Access Token without making the user type in their credentials again.

Request:

Code Block
POST https://mydomain.auth.us-east-1.amazoncognito.com/oauth2/token >
                           Content-Type='application/x-www-form-urlencoded'&
                           Authorization=Basic aSdxd892iujendek328uedj
                           
                           grant_type=refresh_token&
                           client_id=djc98u3jiedmi283eu928&
                           refresh_token=REFRESH_TOKEN

Response:

Code Block
HTTP/1.1 200 OK
                                 Content-Type: application/json
                                 
                                 {
                                  "id_token":"eyJz9sdfsdfsdfsd", 
                                  "access_token":"dmcxd329ujdmkemkd349r",
                                  "token_type":"Bearer", 
                                  "expires_in":3600
                                 }

Check For 401 Status Response To Determine Whether To Use Refresh Token

One simple way t deterine if the Access Token has expired is to check each API call for a 401 status in the response. In this case, use the Refresh Token to get a new short-lived Access Token without additional authentication.

Keep Track Of Expiration Time To Live

A more involved method is to track the expiration TTL when you retrieve your Access Token. If the time has expired, then use the Refresh Token to get a new short-lived Access Token and repeat the API call with the new Access Token.

Info

Related Article: How to check if a user is logged in

Panel
bgColor#FFFFFF

On This Page:

Table of Contents
Panel
bgColor#FFFFFF

More Reading:

Info

Related Article: How to check if a user is logged in