Fortinet white logo
Fortinet white logo

REST API Solution Guide

OAuth server token (/oauth/token/)

OAuth server token (/oauth/token/)

URL: https://[server_name]/api/v1/oauth/token/

This end-point is used to verify a user's identity and upon confirming that identity, issue a token which allows access to resources protected by Bearer Token. Tokens are issued per application and user, and applications are configurable in the GUI. So long as the access token expiry of the application in question isn't zero, then these tokens can expire, and also they can be refreshed. This endpoint can also be used to refresh a previously issued token.

Supported fields

Field

Display name

Type

Required

Other restrictions

username

User username

string

If grant_type is password

iam_account

IAM account name or alias

string

If grant_type is password and username is not specified

Ignored if username is specified.

iam_user

IAM user

string

If grant_type is password and username is not specified

Ignored if username is specified.

password

User password

string

If grant_type is password

realm

User realm

string

If grant_type is password, and user is not local

The default realm is the realm selected as the default under System > Administration > System Access. If you are authenticating a user from the default realm, you do not need to specify a realm.

refresh_token

Token used to refresh access_token

string

If grant_type is refresh_token

grant_type

OAuth grant type

string

Yes

client_id

String ID of client or application

string

Yes

client_secret

Hash client secret

string

If application client_type is 'confidential'

challenge

The type of multi-factor authentication challenge

string

If responding to multi-factor authentication challenge with challenge response

Can be 'otp', 'radius', etc. Reuse the challenge you received from the token endpoint.

challenge_response

String code challenge response

string

If responding to challenge

method

The method of challenge response

string

Yes

Required if responding with an OTP challenge. Can be 'ftm', 'ftm-push', 'ftk', 'sms', 'email', or 'dual'.

session

OAuth grant type

string

If responding with an OTP challenge with ftm-push method

redirect_uri

Redirect URL callback

string

scope

Requested scopes

string

No

This parameter is ignored if the request is not for password-based grant type

code_verifier

High-entropy cryptographic random STRING

See RFC7636 Section-4.1

string

If grant_type is Authorization code with PKCE

The code_challenge is an SHA256 transformation of the code_verifier

code

Single-use authorization code

string

If grant_type is Authorization code or Authorization code with PKCE

Allowed methods

HTTP method

Resource URI

Action

POST

/api/v1/oauth/token/

Get token, or refresh token.

Response

If the openid is specified as scope which is the default one at the moment, JWT token is returned as id_token. This token consists of three parts: Header, Payload, and keys (separated by dots).

Response codes

In addition to the general codes defined in General API response codes, a POST request to this resource can also result in the following return codes:

Code

Response content

Description

200 OK

Valid credentials

401 Unauthorized

Invalid credentials, or user improperly configured

406 Not Acceptable

Challenge, method, status, and optional session

Initial credentials are valid, but the user requires more information. Send additional information.

Example

Get token (Password-based)

curl -k -v -X POST \
https://[FAC_IP]/api/v1/oauth/token/ \
-H 'Content-Type: application/json' \
-d '{
    "username": "luser1",
    "password": "12345678",
    "client_id": "client_id",
    "client_secret": "client_secret", -> in case of confidential
    "grant_type": "password"
}'

Response:
{
    "access_token": "shrWNdu1xJRUgpcUi2bhYRX1Sl8pXe",
    "expires_in": 0,
    "message": "successfully authenticated",
    "refresh_token": "tU85BMdOoV3pktSSiLaABJN7ySiADZ",
    "scope": "read",
    "status": "success",
    "token_type": "Bearer"
}

Get token (Authorization code)

curl -k -v -X POST \
https://[FAC_IP]/api/v1/oauth/token/ \
-H 'Content-Type: application/json' \
-d '{
    "username": "luser1",
    "password": "12345678",
    "client_id": "client_id",
    "client_secret": "client_secret",
    "code": "04yjZyQNtsRKe9yzFBnmj9gf4wCdsY"
    "grant_type": "authorization_code"
}'

Response:
{
    "access_token": "nCKp5jGTfPGuk2Rv98chYUrBYqlhxZ",
    "expires_in": 3600,
    "token_type": "Bearer",
    "scope": "openid",
    "refresh_token": "5HibwqzdhCbWD3jEPP89FZJ5uJYxhd",
    "id_token": "eyJ0eXAiOiAiSldUIiwgImFsZyI6ICJSUzI1NiIsICJraWQiOiAiZUE5VGxDTmE2cWo5OTRHeUg0VGtRZ1F0UV9QT0NFc3JTazlGTFF0b0dOVSJ9.eyJhdWQiOiAiaGxjT1pQTUdoSWpOZ1U0c1p1OTBubXI0TzZxOXZzU1NkVGNVSXViTSIsICJpYXQiOiAxNjM1ODg1MDUyLCAiYXRfaGFzaCI6ICJtSHpPdUlYWm9qdVNNZURGeV9CS1hBIiwgInN1YiI6ICIyIiwgImlzcyI6ICIvYXBpL3YxL29hdXRoIiwgImV4cCI6IDE2MzU5MjEwNTIsICJqdGkiOiAiNjljNjEyNzktNTBlMi00YjQ3LWFhMGYtOTk0YWVhNjBiMmU0In0.Rd64aeiPT7Tn2xsis3Vbdnu0Zaec0GA_K0VDoNOHBPhYgnMS6rx7tRJhL7A_i3ocOnGVUU7ufP4LVIUuhQx-p_LoDkOD_MoR5PYUNg3M77zEXjdnrRJDiGB9DapwDKFNY_1hyjLbaBl9336kzoSqBxHqrkGDhiZQJvycH1epvZ_CsW0M-VcVBeLtCZKWmFcraklIZKfpg4RaCxTs_fe07eBZL_Iok-Tlpx9R5PIxjAwBiUOoZiUyNmYF8BFQXe7eo2ikZ_WsdvE0sfYFzmdukov4_BdytLXt8Hvqqi2CNw9AFOvszhCLweife_2vBNpiS_vL6r2LpZ7-FCwGsqwTWuqyhuj4LtRodgqnmswrZ6yDEpxNIWCoE7m4u77GG9se7YU8CWllwr__8EZFEvrBB6_YEhAxofHZaBXFXO2aXNW37CTCidLNuXbGlQp2HaJGSQnM7MDbHVbiJ3QyKc0aUWaYYqP5msW9A91Z2-E7PTNp7UptsHnIiVzlfdFYyRskwym8j31WmlwCdS7BvxxgBCSbbanWznIKKiFcgdDOAyN-F6ePOSs8cCbAJoZ_hQSPxYd3ChLBTSL38ZPUTzPxZH7zqG0gLX_uSNkIMBSrqhnLDZGKogCZhuOUNY38UBwNrasAcwEObhuhMuHKYu5GkQZE79bTrcuXeHuxbGGRWQQ"
}

Refresh a token

curl -k -v -X POST \
https://[FAC_IP]/api/v1/oauth/token/ \
-H 'Content-Type: application/json' \
-d '{
    "client_id": "client_id",
    "client_secret": "client_secret", -> in case of confidential
    "grant_type": "refresh_token",
    "refresh_token": "tU85BMdOoV3pktSSiLaABJN7ySiADZ"
}'

Response:
{
    "access_token": "fzMK69MdyA0vRJXh2CWnuHRcpuQrpL",
    "expires_in": 0,
    "message": "Token has been refreshed successfully",
    "refresh_token": "UqCV1xEPSoq4vSLE0YgXAkF2zzMGO5",
    "scope": "read",
    "status": "success",
    "token_type": "Bearer"
}

Get a token with FTM push

curl -k -v -X POST \
https://[FAC_IP]/api/v1/oauth/token/ \
-H 'Content-Type: application/json' \
-d '{
    "username": "luser1",
    "password": "12345678",
    "client_id": "client_id",
    "client_secret": "client_secret", -> in case of confidential
    "grant_type": "password"
}'

Response:
{
    "challenge": "otp",
    "method": "ftm-push",
    "session": "480dccc0f6bf4ed69ba484320ef92781",
    "status": "pending"
}

Check for FTM-PUSH approval

curl -k -v -X GET \
'https://[FAC_IP]/api/v1/pushpoll/?s=480dccc0f6bf4ed69ba484320ef92781' \
-H 'Content-Type: application/json' \

Response if status is 'pending':
{
    "challenge": "otp",
    "method": "ftm-push",
    "session": "480dccc0f6bf4ed69ba484320ef92781",
    "status": "pending"
}

Response if status is 'success' (The push request was approved):
{
    "challenge": "otp",
    "challenge_response": "3njPWHp6LgXtRwwXabEN",
    "method": "ftm-push",
    "session": "480dccc0f6bf4ed69ba484320ef92781",
    "status": "success"
}

Use the successful push session code to get a token

curl -k -v -X POST \
https://[FAC_IP]/api/v1/oauth/token/ \
-H 'Content-Type: application/json' \
-d '{
    "username": "luser1",
    "password": "12345678",
    "client_id": "client_id",
    "grant_type": "password",
    "challenge": "otp",
    "challenge_response": "3njPWHp6LgXtRwwXabEN",
    "method": "ftm-push",
    "session": "480dccc0f6bf4ed69ba484320ef92781"
}'

Response: 
{
    "access_token": "c1t2I989RnZCn7xFNsDGLtGShdeSL6",
    "expires_in": 36000,
    "refresh_token": "nP0Fq74huju4gDLCR5jXHSxerDAXD3",
    "scope": "read",
    "status": "success",
    "token_type": "Bearer"
}

If you opt to manually enter the token code, change the method from ftm-push to ftm

curl -k -v -X POST \
https://[FAC_IP]/api/v1/oauth/token/ \
-H 'Content-Type: application/json' \
-d '{
    "username": "luser1",
    "password": "12345678",
    "client_id": "client_id",
    "grant_type": "password",
    "challenge": "otp",
    "challenge_response": "12345678",
    "method": "ftm"
}'

Response: 
{
    "access_token": "c1t2I989RnZCn7xFNsDGLtGShdeSL6",
    "expires_in": 36000,
    "refresh_token": "nP0Fq74huju4gDLCR5jXHSxerDAXD3",
    "scope": "read",
    "status": "success",
    "token_type": "Bearer"
}

If you opt to manually enter the token code, change the method from ftm-push to ftm:
curl -k -v -X POST \
https://[FAC_IP]/api/v1/oauth/token/ \
-H 'Content-Type: application/json' \
-d '{
    "username": "luser1",
    "password": "12345678",
    "client_id": "client_id",
    "grant_type": "password",
    "challenge": "otp",
    "challenge_response": "12345678",
    "method": "ftm"
}'

Response: 
{
    "access_token": "c1t2I989RnZCn7xFNsDGLtGShdeSL6",
    "expires_in": 36000,
    "refresh_token": "nP0Fq74huju4gDLCR5jXHSxerDAXD3",
    "scope": "read",
    "status": "success",
    "token_type": "Bearer"
}

OAuth server token (/oauth/token/)

OAuth server token (/oauth/token/)

URL: https://[server_name]/api/v1/oauth/token/

This end-point is used to verify a user's identity and upon confirming that identity, issue a token which allows access to resources protected by Bearer Token. Tokens are issued per application and user, and applications are configurable in the GUI. So long as the access token expiry of the application in question isn't zero, then these tokens can expire, and also they can be refreshed. This endpoint can also be used to refresh a previously issued token.

Supported fields

Field

Display name

Type

Required

Other restrictions

username

User username

string

If grant_type is password

iam_account

IAM account name or alias

string

If grant_type is password and username is not specified

Ignored if username is specified.

iam_user

IAM user

string

If grant_type is password and username is not specified

Ignored if username is specified.

password

User password

string

If grant_type is password

realm

User realm

string

If grant_type is password, and user is not local

The default realm is the realm selected as the default under System > Administration > System Access. If you are authenticating a user from the default realm, you do not need to specify a realm.

refresh_token

Token used to refresh access_token

string

If grant_type is refresh_token

grant_type

OAuth grant type

string

Yes

client_id

String ID of client or application

string

Yes

client_secret

Hash client secret

string

If application client_type is 'confidential'

challenge

The type of multi-factor authentication challenge

string

If responding to multi-factor authentication challenge with challenge response

Can be 'otp', 'radius', etc. Reuse the challenge you received from the token endpoint.

challenge_response

String code challenge response

string

If responding to challenge

method

The method of challenge response

string

Yes

Required if responding with an OTP challenge. Can be 'ftm', 'ftm-push', 'ftk', 'sms', 'email', or 'dual'.

session

OAuth grant type

string

If responding with an OTP challenge with ftm-push method

redirect_uri

Redirect URL callback

string

scope

Requested scopes

string

No

This parameter is ignored if the request is not for password-based grant type

code_verifier

High-entropy cryptographic random STRING

See RFC7636 Section-4.1

string

If grant_type is Authorization code with PKCE

The code_challenge is an SHA256 transformation of the code_verifier

code

Single-use authorization code

string

If grant_type is Authorization code or Authorization code with PKCE

Allowed methods

HTTP method

Resource URI

Action

POST

/api/v1/oauth/token/

Get token, or refresh token.

Response

If the openid is specified as scope which is the default one at the moment, JWT token is returned as id_token. This token consists of three parts: Header, Payload, and keys (separated by dots).

Response codes

In addition to the general codes defined in General API response codes, a POST request to this resource can also result in the following return codes:

Code

Response content

Description

200 OK

Valid credentials

401 Unauthorized

Invalid credentials, or user improperly configured

406 Not Acceptable

Challenge, method, status, and optional session

Initial credentials are valid, but the user requires more information. Send additional information.

Example

Get token (Password-based)

curl -k -v -X POST \
https://[FAC_IP]/api/v1/oauth/token/ \
-H 'Content-Type: application/json' \
-d '{
    "username": "luser1",
    "password": "12345678",
    "client_id": "client_id",
    "client_secret": "client_secret", -> in case of confidential
    "grant_type": "password"
}'

Response:
{
    "access_token": "shrWNdu1xJRUgpcUi2bhYRX1Sl8pXe",
    "expires_in": 0,
    "message": "successfully authenticated",
    "refresh_token": "tU85BMdOoV3pktSSiLaABJN7ySiADZ",
    "scope": "read",
    "status": "success",
    "token_type": "Bearer"
}

Get token (Authorization code)

curl -k -v -X POST \
https://[FAC_IP]/api/v1/oauth/token/ \
-H 'Content-Type: application/json' \
-d '{
    "username": "luser1",
    "password": "12345678",
    "client_id": "client_id",
    "client_secret": "client_secret",
    "code": "04yjZyQNtsRKe9yzFBnmj9gf4wCdsY"
    "grant_type": "authorization_code"
}'

Response:
{
    "access_token": "nCKp5jGTfPGuk2Rv98chYUrBYqlhxZ",
    "expires_in": 3600,
    "token_type": "Bearer",
    "scope": "openid",
    "refresh_token": "5HibwqzdhCbWD3jEPP89FZJ5uJYxhd",
    "id_token": "eyJ0eXAiOiAiSldUIiwgImFsZyI6ICJSUzI1NiIsICJraWQiOiAiZUE5VGxDTmE2cWo5OTRHeUg0VGtRZ1F0UV9QT0NFc3JTazlGTFF0b0dOVSJ9.eyJhdWQiOiAiaGxjT1pQTUdoSWpOZ1U0c1p1OTBubXI0TzZxOXZzU1NkVGNVSXViTSIsICJpYXQiOiAxNjM1ODg1MDUyLCAiYXRfaGFzaCI6ICJtSHpPdUlYWm9qdVNNZURGeV9CS1hBIiwgInN1YiI6ICIyIiwgImlzcyI6ICIvYXBpL3YxL29hdXRoIiwgImV4cCI6IDE2MzU5MjEwNTIsICJqdGkiOiAiNjljNjEyNzktNTBlMi00YjQ3LWFhMGYtOTk0YWVhNjBiMmU0In0.Rd64aeiPT7Tn2xsis3Vbdnu0Zaec0GA_K0VDoNOHBPhYgnMS6rx7tRJhL7A_i3ocOnGVUU7ufP4LVIUuhQx-p_LoDkOD_MoR5PYUNg3M77zEXjdnrRJDiGB9DapwDKFNY_1hyjLbaBl9336kzoSqBxHqrkGDhiZQJvycH1epvZ_CsW0M-VcVBeLtCZKWmFcraklIZKfpg4RaCxTs_fe07eBZL_Iok-Tlpx9R5PIxjAwBiUOoZiUyNmYF8BFQXe7eo2ikZ_WsdvE0sfYFzmdukov4_BdytLXt8Hvqqi2CNw9AFOvszhCLweife_2vBNpiS_vL6r2LpZ7-FCwGsqwTWuqyhuj4LtRodgqnmswrZ6yDEpxNIWCoE7m4u77GG9se7YU8CWllwr__8EZFEvrBB6_YEhAxofHZaBXFXO2aXNW37CTCidLNuXbGlQp2HaJGSQnM7MDbHVbiJ3QyKc0aUWaYYqP5msW9A91Z2-E7PTNp7UptsHnIiVzlfdFYyRskwym8j31WmlwCdS7BvxxgBCSbbanWznIKKiFcgdDOAyN-F6ePOSs8cCbAJoZ_hQSPxYd3ChLBTSL38ZPUTzPxZH7zqG0gLX_uSNkIMBSrqhnLDZGKogCZhuOUNY38UBwNrasAcwEObhuhMuHKYu5GkQZE79bTrcuXeHuxbGGRWQQ"
}

Refresh a token

curl -k -v -X POST \
https://[FAC_IP]/api/v1/oauth/token/ \
-H 'Content-Type: application/json' \
-d '{
    "client_id": "client_id",
    "client_secret": "client_secret", -> in case of confidential
    "grant_type": "refresh_token",
    "refresh_token": "tU85BMdOoV3pktSSiLaABJN7ySiADZ"
}'

Response:
{
    "access_token": "fzMK69MdyA0vRJXh2CWnuHRcpuQrpL",
    "expires_in": 0,
    "message": "Token has been refreshed successfully",
    "refresh_token": "UqCV1xEPSoq4vSLE0YgXAkF2zzMGO5",
    "scope": "read",
    "status": "success",
    "token_type": "Bearer"
}

Get a token with FTM push

curl -k -v -X POST \
https://[FAC_IP]/api/v1/oauth/token/ \
-H 'Content-Type: application/json' \
-d '{
    "username": "luser1",
    "password": "12345678",
    "client_id": "client_id",
    "client_secret": "client_secret", -> in case of confidential
    "grant_type": "password"
}'

Response:
{
    "challenge": "otp",
    "method": "ftm-push",
    "session": "480dccc0f6bf4ed69ba484320ef92781",
    "status": "pending"
}

Check for FTM-PUSH approval

curl -k -v -X GET \
'https://[FAC_IP]/api/v1/pushpoll/?s=480dccc0f6bf4ed69ba484320ef92781' \
-H 'Content-Type: application/json' \

Response if status is 'pending':
{
    "challenge": "otp",
    "method": "ftm-push",
    "session": "480dccc0f6bf4ed69ba484320ef92781",
    "status": "pending"
}

Response if status is 'success' (The push request was approved):
{
    "challenge": "otp",
    "challenge_response": "3njPWHp6LgXtRwwXabEN",
    "method": "ftm-push",
    "session": "480dccc0f6bf4ed69ba484320ef92781",
    "status": "success"
}

Use the successful push session code to get a token

curl -k -v -X POST \
https://[FAC_IP]/api/v1/oauth/token/ \
-H 'Content-Type: application/json' \
-d '{
    "username": "luser1",
    "password": "12345678",
    "client_id": "client_id",
    "grant_type": "password",
    "challenge": "otp",
    "challenge_response": "3njPWHp6LgXtRwwXabEN",
    "method": "ftm-push",
    "session": "480dccc0f6bf4ed69ba484320ef92781"
}'

Response: 
{
    "access_token": "c1t2I989RnZCn7xFNsDGLtGShdeSL6",
    "expires_in": 36000,
    "refresh_token": "nP0Fq74huju4gDLCR5jXHSxerDAXD3",
    "scope": "read",
    "status": "success",
    "token_type": "Bearer"
}

If you opt to manually enter the token code, change the method from ftm-push to ftm

curl -k -v -X POST \
https://[FAC_IP]/api/v1/oauth/token/ \
-H 'Content-Type: application/json' \
-d '{
    "username": "luser1",
    "password": "12345678",
    "client_id": "client_id",
    "grant_type": "password",
    "challenge": "otp",
    "challenge_response": "12345678",
    "method": "ftm"
}'

Response: 
{
    "access_token": "c1t2I989RnZCn7xFNsDGLtGShdeSL6",
    "expires_in": 36000,
    "refresh_token": "nP0Fq74huju4gDLCR5jXHSxerDAXD3",
    "scope": "read",
    "status": "success",
    "token_type": "Bearer"
}

If you opt to manually enter the token code, change the method from ftm-push to ftm:
curl -k -v -X POST \
https://[FAC_IP]/api/v1/oauth/token/ \
-H 'Content-Type: application/json' \
-d '{
    "username": "luser1",
    "password": "12345678",
    "client_id": "client_id",
    "grant_type": "password",
    "challenge": "otp",
    "challenge_response": "12345678",
    "method": "ftm"
}'

Response: 
{
    "access_token": "c1t2I989RnZCn7xFNsDGLtGShdeSL6",
    "expires_in": 36000,
    "refresh_token": "nP0Fq74huju4gDLCR5jXHSxerDAXD3",
    "scope": "read",
    "status": "success",
    "token_type": "Bearer"
}