Web Authentication Flow

Resources and Guides

Overview

The LevelUp OpenID Connect flow is a layer on top of the LevelUp OAuth2 authorization flow and provides external apps the means for authenticating users.

Web Application Flow

This is a description of the OpenID Connect flow from third-party web sites - it is not intended for use in a mobile app.

1. Redirect user to request LevelUp access

URL

GET https://www.thelevelup.com/oauth2/authorizations/new

Request URL Format

https://www.thelevelup.com/oauth2/authorizations/new?client_id=API_KEY&
redirect_uri=REDIRECT_URI&response_type=code&scope=PERMISSIONS_LIST&state=CSRF_TOKEN

Request Parameters

Param Required Description
client_id Yes Your API Key.
redirect_uri Yes The URI in your app where users will be sent after authorization. Must match a registered redirect_uri for your app. Must be secured with SSL/TLS and must use ‘https’ URI scheme.
login_hint No User’s email.
first_name No User’s first name.
last_name No User’s last name.
response_type Yes Always code in the web OAuth2 flow.
scope Yes Space-separated list of permission names that the access token will have granted to it. Make sure you include “openid” in the permissions list.
state Yes Unique random token generated to verify using CSRF protection. Should use urlsafe encoding and should generally not exceed 100 characters.

Example URL

https://sandbox.thelevelup.com/oauth2/authorizations/new?
client_id=23eef8c2895ce66eb4500bb5e324b200f5339e6fe6d8665f6de0205f43f3b563&
redirect_uri=https://example.com/oauth2_redirect_uri&
response_type=code&scope=read_user_basic_info%20read_qr_code%20openid&
login_hint=sandboxdevexample@thelevelup.com&state=8675309

Enter the password fod2yau4flu6vok6 to view the redirect.

2. LevelUp redirects back to your site

If the user accepts your request, LevelUp redirects back to your site with a one-time code and the state you provided in the previous step as URL parameters in the form REDIRECT_URI?code=CODE&state=PASSED_STATE. If the states don’t match, the request has been made by a third party and the process should be aborted.

If there is an error, the user will still be redirected however instead of a code param there will be an error param stating the error case.

The redirect URI must be HTTPS.

Note: In the event that the user’s email is not associated with a LevelUp account, LevelUp will create a user account and ask the user to add a funding source via a web form.

Example Redirect URL

https://example.com/oauth2_redirect_uri?code=7-fedbd1e54b2b7f5c9c9a9f5a87a89bf4e0901c8a0ab62da9c9e4d07b0d526b&state=8675309

3. Exchange one-time code for an access token

Using the code passed in from the previous step:

URL

POST https://www.thelevelup.com/oauth2/tokens

POST Parameters

The parameters should be form encoded in the body of the request.

Param Required Description
client_id Yes Your API Key.
client_secret Yes Your client secret.
code Yes Code received in the REDIRECT_URI.
grant_type Yes Always authorization_code.
redirect_uri Yes The redirect_uri you used in the original request.

cURL Example

curl -X POST -H Accept:application/json \
-F client_id=23eef8c2895ce66eb4500bb5e324b200f5339e6fe6d8665f6de0205f43f3b563 \
-F client_secret=4d71e958b9fb6a62af624390c4ef394df15d168ea12b3b12735643ff0694520f \
-F code=7-fedbd1e54b2b7f5c9c9a9f5a87a89bf4e0901c8a0ab62da9c9e4d07b0d526b \
-F grant_type=authorization_code \
-F redirect_uri=https://example.com/oauth2_redirect_uri \
https://sandbox.thelevelup.com/oauth2/tokens

Since this request requires the client_secret, it must be made from your server, not directly from consumer devices. The client_secret should never be shipped in apps or exposed to web clients directly. Make sure you also take care that the client_secret is never checked in to any source control (git, mercurial etc).

The one-time code expires after 10 minutes. If you try to exchange the code for a token after the expiration time or more than once, the request will be rejected and any token already granted will be invalidated.

Note: If you’d like to replicate the example call yourself, use the code returned to you in the redirect above.

Response

By default, the response will take the following form:

{
    "access_token": "1922-d692a6116165e602db02a1309c8e7a4bb6bd16fe252ed396d7aab93631a274",
    "id_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzUxMiJ9.eyJhdWQiOiIyM2VlZjhjMjg5NWNlN
    jZlYjQ1MDBiYjVlMzI0YjIwMGY1MzM5ZTZmZTZkODY2NWY2ZGUwMjA1ZjQzZjNiNTYzIiwiZXhwIjox
    NDI3Mzg4MTI3LCJpYXQiOjE0MjczODc1MjcsImlzcyI6Imh0dHBzOi8vc2FuZGJveC50aGVsZXZlbHV
    wLmNvbSIsInN1YiI6Mjg1LCJhdF9oYXNoIjoibmttX1JzS1FUdnNQOFE0Mnk3OEVmSVJDNTJyVFItRV
    QtcGxrSWM1SHg4RSJ9.he9lWeQb-2l4rNjVCMIprwKYHWIV7vGAoQHZjcyoHoFSpEdPMq2ERvrvQEXs
    E0cEyBHj10e42ik5gvFTbH6KSUp2lMgcOfk4LAydoIUOMJdoegZ2NI8jGp-Mc37zVIqZ-4ExAdH2RpD
    f2KePlu44w8JM34CzYW6dJYfe490up1oFRdeK7OZm-uyz1NnJ-OA8rZdGozCpU120nqG_075ujkFlH4
    3V-loWYHovoB0LbPALndQFe2_hEDX9bkhsy35i8jeEm_4q7yGnanNmReZfVu_m6wXyUl1Yl5sDvY8LQ
    GKHdV8LBSNxu3x6a0u_3Qg6PAW_gvxqgOweKRpv6c3ES_Bzn-2Ul076JaKzVgKlFZ6OPIinvkRiWkpt
    0CX6gn11pwJeb7NDtVdhx8RFynM4HwRPdAPLTQk3QUnVaOETLpJ3gTD5VUaUSY005QQoyCZ1L4dOajA
    24pPIJ9c77yQofzOtu0Yn0zwUFWPYCFvvRLptqSC4LWYrrl7RZSUmsL0pyxrDQz-4bUjdWqS1joHZCf
    0Txmzg5jO704oyRTkFgYLbeEWM60I8UIkdOhSm6qn-a-r_JJtP02AT6i7djFROVNd7UFyS_ZpRYEwJD
    LDiZGUZKVzxHjf9cKgyWQZtueNaLq7o17_HoYaOrtIyjaey9-XCgfxjUwaF7gOz-CzMhqM"
}

4. Obtain user information from the ID Token

The ID Token is a JWT (JSON Web Token), a base64url-encoded, cryptographically signed JSON object. LevelUp ID tokens may contain the following fields (also known as claims):

Param Type Description
iss String “https://www.thelevelup.com” or “https://sandbox.thelevelup.com”
sub Integer App-specific ID for the user, for referencing the user in your system.
aud Integer The API key of the app that made that request
exp Epoch time in seconds Time id_token expires
iat Epoch time in seconds Time id_token issued
at_hash String Access token hash. Provides validation that the access token is tied to the identity token. If the ID token is issued with an access token in the server flow, this is always included.

To verify the id_token signature, you will need the public key associated with the environment you are using.

Sandbox Public Key
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA5+FgHAg3vZt7qaDMMsDQ
Q+g1e7X5tVSaZPSNtgsx4waS6R1pLYWSZVDA9mGX/te0eRV+I5PvY7gwExK5lnH6
K9ofGxVh5O1MSJFBP/vnzY+8YDYtyygid4ihn6zXbaSLgzbT2CmbHeDOe1T2QUdU
bOoDYr8KR5qgITs7g9lcJYRRASJHKgEehptHZGn3nuPvJbbVMikUqEtPn4MwZb9s
+IaXF5ET24+0KMpEzMV15PwnFjRmIeXKAIs61JZOoztZnp1kU27rldIbS5uCwOUi
yz4p/9GvlaUJp7C+MMxOltFiRSGaQv0y0VwdJ6C9aD8e7AUqF85h8ugnEjuGW2Qr
wYTnJClKqH04i8ghkuJ6gR4lWf1rbQXjlBuqF9tgnllGXY+JnG6HoqOzXf3qisBy
sLclKSIyryXfcVHWpha1g6OSA7pFU8misrBe6I5WumOCkGIN/97Gb3EAOaHKi5dk
rTAuLdxF357Y4yXFFVwcikrwLx7NaXeJP4Pv2qCyyPFuCpE3rYRfxd8jbkFs38RA
xHGtI58D5gRnz4V+3ozxQl6R4c0O8j0tAJsXnGIkK3/9Jk9ThFXkI8fD0++drKOL
6sJLatSSUTPuVU52oWdAZ+xcHoG3L4bYPkpyrwyNoBt8ULHIXTcd7nPCpuu+0UQN
R6rOCy2TMOzU2pc+riTWwl8CAwEAAQ==
-----END PUBLIC KEY-----
Production Public Key
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAq+o1TYox26NV3wyDcYgr
b0GWJTGLZEU6JJtlx2Pnq74mMjZSBEXF0S88pyxuBJk0nJWRiVYY2ndBcOJkDX2v
wr6wrWCte4zNOBwe3ZXQwjn6BB6GOFmTflBAPPUOaCKyF+8ShjSRnb4hL5wJUBUP
4oyGSfr+8vob8BFzV1m9/nAavY3mYZ/YILiuEbD9RkS8GWStwQC9vDyrR9iFsARD
kBJMZJwJUhptQIMhZVvHxRphoNGXPYRPk6qX5rofllxk9JRjiBpe8pUU0CjwRcOX
5TpUtgE9anKnUzOwYmMPhE8tOtiWxB+KfDGygt0Ehyhta3tV3N/sAAjmbjFhgAvY
LYt2J4Hqzx0SxXQiow91NP+gBYXexxlMKQ/dR2NQes6VgBGCkRP0+5WpiNGCMCIA
ygVdxvMJ7q68kf+t5TA+seqeu1P4XlmZ5oL45TceQYMUm9iXCxfP49a855TOmRnB
uqpLpo5JcxTlqnvlzuwmdjKkk0SPrMDv+ztslPN/vclJEA7ehktadWDqDLKnss7k
Kj46ybLSum6w1FLrcAvIDtbAJbXvCHi3950hvSnMHOTf5epyqirnmNa0rZsoPIka
RNchWmMEnlkvUOYxGoyKlvwktFaOEYDLKD/q35iKhhFfXN4aD3XoygyCqYNdoYCA
MdY2dRMzr0vC7m1EbrePCkcCAwEAAQ==
-----END PUBLIC KEY-----

There are many libraries that can be used to verify the JWT. For example, the jwt gem for ruby:

JWT.decode(id_token, OpenSSL::PKey::RSA.new(public_key_string))

[{
    "aud" => "23eef8c2895ce66eb4500bb5e324b200f5339e6fe6d8665f6de0205f43f3b563",
    "exp" => 1427382978,
    "iat" => 1427382378,
    "iss" => "https://sandbox.thelevelup.com",
    "sub" => 285,
    "at_hash" => "NDlT67MFu6JqCw91QEQEUl48tNx5HR1IyDjLAqFBhP0"
}, {
    "typ" => "JWT",
    "alg" => "RS512"
}]

Additional libraries can be found at jwt.io.

5. Validate the ID Token

Validation of an ID tokens requires several steps:

  1. Verify that the ID token is the JWT which is properly signed with the appropriate LevelUp public key.
  2. Verify that aud is equal to your app’s API key (client_id)
  3. Verify that the value of iss in the ID token is equal to the https://www.thelevelup.com or https://sandbox.thelevelup.com (depending on your environment)
  4. Verify that the expiry time (exp) of the ID token has not passed.

6. Use the access token to access the API

The access token (user token) allows you to make requests to the API on behalf of a user. For details, see the LevelUp API documentation.