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
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

Allowed methods

HTTP method Resource URI Action
POST /api/v1/oauth/token/ Get token, or refresh token.

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
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

Allowed methods

HTTP method Resource URI Action
POST /api/v1/oauth/token/ Get token, or refresh token.

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"
}