Authorization code flow (3-legged OAuth)
Authorize your app to act on behalf of Indeed user accounts.
By using this API and its documentation and building an integration, you agree to the Additional API Terms and Guidelines.
Authorization code flow (3-legged OAuth) overview
Use the authorization code flow (3-legged OAuth) to authorize your app to act on behalf of Indeed user accounts and those users' associated employer accounts.
For an overview of Indeed authorization and authentication, see OAuth at Indeed.
Authorization code flow (3-legged OAuth) steps
Frequency | # | Step |
---|---|---|
Once | 1. | |
2. | ||
For each app | 3. | |
4. | ||
5. | ||
For each API call | 6. |
You can also complete these actions:
Action | Description |
---|---|
Enable users to select an employer account. Then, get an access token that represents that employer. | |
Get information about the user account that registered an app. | |
Indeed limits the number of redirect URLs to five, which conforms to the security best practices for OAuth apps. You can dynamically redirect a user to multiple URLs. |
See also Guidelines.
Get access token that represents employer
An Indeed API might require you to represent an employer or an advertiser with an access token.
You can show the user either:
On either screen, a user selects an employer from the list of employers associated with the user.
Then, you get an access token for that employer.
An access token can represent only one employer. To switch employers, refresh your access token.
Show the Indeed employer selection screen
-
To request the creation of an authorization link to display the Indeed employer selection screen, call the
https://secure.indeed.com/oauth/v2/authorize
endpoint with theprompt=select_employer
andscope=employer_access
query parameters.For example, this call includes both the
prompt=select_employer
andscope=employer_access
query parameters:https://secure.indeed.com/oauth/v2/authorize?client_id=bf7622efee705862320df0f5c7690b22f60ba24f236aaf4adf5b7a36fa0adcf1&redirect_uri=https%3A%2F%2Fexample.com%2Foauth&response_type=code&state=random&scope=email+offline_access+employer_access&prompt=select_employerThis authorization link triggers these screens to appear:
Screen Description Authentication
Appears when the user is logged out of Indeed.
OAuth consent
Enables a user to grant consent for any scopes that the OAuth app requests, such as the
employer_access
scope.Indeed employer selection
Enables a user to select an employer from a list of employers associated with the user account.
Use Partner Console to view what the OAuth consent screen looks like to your users.
-
If the user selects an employer, a redirect URI parameter transmits the employer ID to your OAuth app:
https://example.com/oauth/callback?state=random&employer=6d2f02224e30d401810b1726eb246d8d&code=e_IEr5UlBysThe URL includes an
employer
parameter, which contains an employer ID value.Don't assume that the redirect URI includes an
employer
parameter even when you use theprompt=select_employer
parameter. -
Proceed to Get employer access token.
Show a custom employer selection screen
Although Indeed recommends that you enable users to select an employer from the standard Indeed employer selection screen, you can also create a custom employer selection screen:
-
Get an access token to trigger the OAuth consent screen. When you get the token, request the
employer_access
andoffline_access
scopes.The query returns an access token, ID token, and refresh token.
-
To list employers for the current user, use the JSON Web Tokens Debugger to decode the ID token.
-
Build a custom employer selection screen that enables the user to select an employer.
-
Proceed to Get employer access token.
Get employer access token
Get an access token that represents the employer that the user selects from the employer selection screen.
-
Call the
https://apis.indeed.com/oauth/v2/tokens
endpoint with theemployer
parameter, with the HTTPAccept
andContent-Type
request headers.Use the ID of the employer that the user selected to get an access token that represents that employer:
curl -X POST -H 'Content-Type: application/x-www-form-urlencoded' -H 'Accept: application/json' \-d 'grant_type=authorization_code' \-d 'client_id=bf7622efee705862320df0f5c7690b22f60ba24f236aaf4adf5b7a36fa0adcf1' \-d 'client_secret=02KKpg6yLXw2v3FKf5lqyFGtMQCvPBNbJIw89SoSd9fts1LAdlvwUQQ6dwhAhEXv' \-d 'code=e_IEr5UlBys' \-d 'redirect_uri=https://example.com/oauth' \-d 'employer=6d2f02224e30d401810b1726eb246d8d' \https://apis.indeed.com/oauth/v2/tokensInclude these request body parameters for oauth/v2/tokens:
Request body parameter Required Value grant_type
✔ authorization_code
Or:
refresh_token
When you use a refresh token to get an access token, an OAuth consent screen is not necessary.
client_id
✔ Your client ID.
client_secret
✔ Your client secret.
code
✔ if you use an authorization code to get an access token The authorization code. redirect_uri
✔ Your URL-encoded redirect URL. refresh_token
✔ if you use a refresh token to get an access token The refresh token. employer
✔ An employer ID. This request returns an access token that represents that employer.
Use this access token for API calls on behalf of the consenting user and only for this employer.
You can also use the
employer
parameter when you exchange a refresh token for an access token.If the user does not select an employer or the user account has no associated employers, then the redirect URI does not include an
employer
parameter.If you request an access token for an employer that is not associated with the user that registered the app, this error occurs:
{"error_description": "Invalid request","error": "invalid_request"}
Get user information
To get information about the user account that registers an app, use either the:
ID token
An ID token is a Base64-encoded JSON Web Token (JWT) that you get automatically when you Get an access token. This token proves that the user has been authenticated.
An Indeed API reads an access token while a third-party app reads an ID token to verify the user's identity.
The ID token contains information about the current user. See id_token
.
Because the JSON Web Token is signed, use the public key to verify that the token is valid:
https://secure.indeed.com/.well-known/keys
For information about ID tokens, see ID Token in the OpenID Connect Core 1.0 incorporating errata set 1 specification.
-
So that the ID token includes the
email
andemail_verified
fields, your app must get theemail
scope. -
Request an access token:
curl -X POST -H 'Content-Type: application/x-www-form-urlencoded' -H 'Accept: application/json' \-d 'code=qCwk_cdC4Ms' \-d 'client_id=a0c3b1092225d3e99f85d7aa3fe1e6001f9a0bb798717cbc2008e58fbda3ef16' \-d 'client_secret=1YFoyZOWmr83njlsIuyCL9QQq5jZkRCR4UtmHGp22MRzjIhe5RbynnAGmuYLFbYx' \-d 'redirect_uri=http%3A%2F%2Flocalhost%3A3000%2Foauth%2Fcallback' \-d 'grant_type=authorization_code' \https://apis.indeed.com/oauth/v2/tokensThe JSON response shows the
id_token
field:{"access_token": "eyJraWQiOiINiYzIwMDh9hrYboL9BMnU_Pfbv41Nqj3nUuMbprUtRgQ","convid": "1erq23om7t5bu800","scope": "email employer_access","id_token": "eyJraWQiMWQ4NTciLCJ0eXAiOiJKV1LmNvbSzNjMwfQ.Jrb1fX-aPtkV9nQK9U1LFP0V61eEApo3pFFPaGjT9zA","token_type": "Bearer","expires_in": 3600} -
To decode the ID token value, copy it into the JSON Web Tokens Debugger.
-
If the user does not grant your app any scopes, the response shows the
sub
field, which is the user's account ID:{"sub": "d2d1962c0664d970"} -
If the user grants your app the
email
andemployer_access
scopes, the response shows theemail
andemail_verified
fields:{"aud": "a0c3b1092225d3e99f85d7aa3fe1e6001f9a0bb798717cbc2008e58fbda3ef16","sub": "d2d1962c0664d970","employers": [{"id": "13ef9940a7c1f0500a7e411e74178c4e","name": "Dharma Initiative"}, {"id": "6d2f02224e30d401810b1726eb246d8d","name": "Umbrella Corporation"}],"email_verified": true,"iss": "https://secure.indeed.com","exp": 1610417960,"iat": 1610414360,"email": "swalther@indeed.com"}
-
The userinfo endpoint
To get account information for the current user, call the v2/api/userinfo
endpoint, which returns the same information that the ID token returns.
For example, you need to get account information when you create Log in with Indeed buttons.
The URL path is:
GET/POST https://secure.indeed.com/v2/api/userinfo
This endpoint does not have any query parameters or request body parameters.
In this request, pass the access token in the Authorization
header with the Bearer
authentication scheme.
Authorization: Bearer <token>
where <token>
is the your access token.
For example:
GET /v2/api/userinfo HTTP/1.1Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5cHost: secure.indeed.com
A successful request returns the HTTP status code 200
and a response payload:
HTTP/1.1 200 OKContent-Type: application/json
{ "sub": "248289761001", "email": "mina.ray@myemail.world", "email_verified": true}
See Response fields for v2/api/userinfo.
To call the v2/api/userinfo
endpoint:
-
Request the
email
scope to return theemail
andemail_verified
fields. -
Get an access token with the authorization code grant type.
-
Call the
userinfo
endpoint.This curl command shows how to call the endpoint, with a shortened token for readability:
curl -H 'Authorization:Bearer eyJraWQiOiI1OTdjYTgxNC03YTA2LTR0zh0Elm9A' \https://secure.indeed.com/v2/api/userinfoThe
userinfo
endpoint returns information for the scopes that a user grants to your OAuth app:-
If the user does not grant your app any scopes, the response shows the
sub
field, which is the user's account ID:{"sub": "d2d1962c0664d970"} -
If the user grants your app the
email
scope, the response shows theemail
andemail_verified
fields:{"sub": "a95064930d19bbc7","email": "swalther+samples@indeed.com","email_verified": true} -
If the user grants your app the
employer_access
scope, the response lists employers, or advertisers, for the user account:{"sub": "bc8c847009a955c9","email": "swalther+employer@indeed.com","email_verified": true,"employers": [{"id": "084a39249af95beedfb90cc5d2b8833c","name": "Dharma Initiative"},{"id": "865e08b649774436ee1f410b611fad7c","name": "Umbrella Corporation"},{"id": "4bc393648e880bc94dd6cef8efbc8486","name": "US Robotics and Mechanical Men"}]}
-
Dynamically redirect a user to multiple URLs
When you register an OAuth client app that uses the authorization code flow (3-legged OAuth), Indeed limits the number of redirect URLs to five, which conforms to the security best practices for OAuth OAuth apps.
To dynamically redirect a user to multiple URLs:
-
Add a
state
parameter to your authorize URL:https://secure.indeed.com/oauth/v2/authorize?client_id=6nwwcdklwgktryjw2j5fxh5t2fyneule7zg7mvw3pf9jbx3wmewzlxkdz1jxvs6b&redirect_uri=http%3A%2F%2Fwww.acerecruitersllc.com%2Foauth%2Findeed&response_type=code&scope=email+offline_access+employer_access&state=AnyValue -
After the Indeed user completes the authorization code flow (3-legged OAuth), Indeed returns the
state
query parameter value in your redirect URL:GET http://www.acerecruitersllc.com/oauth/indeed?code=rXZSMNyYQHQ&state=AnyValue -
To pass a URL with the
state
parameter, such ashttps://somesite.com
, URL-encode it:https://secure.indeed.com/oauth/v2/authorize?client_id=6nwwcdklwgktryjw2j5fxh5t2fyneule7zg7mvw3pf9jbx3wmewzlxkdz1jxvs6b&redirect_uri=http%3A%2F%2Fwww.acerecruitersllc.com%2Foauth%2Findeed&response_type=code&scope=email+offline_access+employer_access&state=https%3A%2F%2Fsomesite.com -
When Indeed redirects the user to your app, use the
state
parameter value to redirect them to another destination, such ashttps://somesite.com
.
Guidelines
Prevent the authorization code from leaking
If you redirect a user to an untrusted website, you inadvertedly reveal the OAuth authorization code in the HTTP Referer
header, which contains the URL that requested a page.
You might unintentionally expose the authorization code to the website that the state
parameter represents. That website likely logs the authorization code in its website logs.
To prevent the authorization code from leaking, redirect the user to another trusted page in your app before you redirect them to the untrusted app. The HTTP Referer
header reveals only the latest URL and not any URLs requested before that.
Do not append query parameters to the redirect URI
Currently, Indeed supports query parameters in the redirect_uri
parameter:
https://secure.indeed.com/oauth/v2/authorize?client_id=80f9f4bd6a34cac31daebe1a093a606ce6b34e91ae6cfa139432ae387269a529&response_type=code&state=random&scope=email+offline_access+employer_access&redirect_uri=https%3A%2F%2Fsomesite.com%3Freturn%3Dhttps%3A%2F%2Fsomeothersite.com
In this example, the https://secure.indeed.com/oauth/v2/authorize<
endpoint includes a redirect_uri
parameter.
The redirect_uri
parameter value is https://somesite.com?return=https://someothersite.com
and includes the return
query parameter, which contains another redirect URL.
Indeed encourages you to use the state
parameter rather than using query parameters in the redirect_uri
parameter.