This article describes the GeneXus Access Manager (GAM) Endpoints in order to explain authentication with GAM as IDP using the OAuth 2.0 protocol.
Requirements:
Define a GAM Application that will be the client that you want to connect to the IDP Server. Get the Client ID and the Client Secret credentials from this application.

When creating the application, you must assign it a name, enable the Allow Authentication property within the WEB Identity Provider. Configure the URL of the Login Object and in the Callback URL property configure the address of the application to integrate. When confirming, the ClientID and Client Secret will be generated.
In case of using PKCE, ensure to set OAuth2.0 Option combo in "Basic and PKCE" or "PKCE", using GAM API the code will be the following:
&GAMApplication.ClientAllowRemoteAuthenticationOAuth20Option = GAMOAuth20Options.BasicPKCE / GAMOAuth20Options.PKCE
Setting GAMOAuth20Options.BasicPKCE means that this application will support both options PKCE and Basic, and this enable that this application can receive PKCE parameters (code_challenge, code_verifier, etc) or not.

Endpoints:
The endpoint is: https://<idp_domain>/<virtual_dir>/oauth/gam/signin.
** When using PKCE, three values must be generated: method, challenge, and verifier.
The first two are sent at the time of authentication, and the verifier must be stored and sent to request a token once the code is received.
Parms:
response_type=code: It's required, but in case it is not received, it's required "oauth=auth".
scope: Scope of the user account you wish to access. It's only required when "&GAMApplication.ClientAuthenticationRequestMustIncludeUserScopes" it's True.
client_id: Client ID of the application, required.
redirect_uri: Callback URL (it must match the one configured in the application). https://<your_server>/<virtual_directory>/oauth/callback, required.
state: Random string that stores the status before the request, required.
**code_challenge_method: S256 or PLAIN, required in case of using PKCE.
**code_challenge: <random_generated>, required in case of using PKCE.
If your application does not contain that Friendly URL (/oauth/callback), you can specify another Custom URL. For example if your application have https://<your_server>/<virtual_directory>/oauth/return you must configure this URL in the IDP Server and check Custom Callback URL property.
Check possible Scopes: OAuth User Scopes
Redirect to:
https://<idp_domain>/<virtual_dir>/oauth/gam/signin?response_type=code&scope=gam_user_data&client_id=<Client_ID>&redirect_uri=https://<your_server>/<virtual_directory>/oauth/callback&state=<random_alphanumeric>
After authenticate you will be automatically redirected to redirect_uri, including the following parameters:code and state, this state is the same as the received.
For example: https://<your_server>/<virtual_directory>/oauth/callback?state=<random_alphanumeric>&code=e8279ad27bfd4e6ca717191cfc74fe4d413494378b53da98ca954924ac6791eb0ab56c06
The developer must validate that the value of the state is the same as the one sent to the IDP Server.
The endpoint is: https://<idp_domain>/<virtual_dir>/oauth/gam/access_token.
POST
Headers:
Content-Type: Type of content that will be returned. Use application/x-www-form-urlencoded
Body:
grant_type=authorization_code: It's required.
code: Code obtained in the Step 1, required.
client_id: Client ID of the application, required.
client_secret: Client Secret of the application, required.
redirect_uri: Callback URL (it must match the one configured in the application). https://<your_server>/<virtual_directory>/oauth/callback, required.
**code_verifier: <random_generated>, same generated at Step 1, required in case of using PKCE.
POSTMAN Example:


Response:
In response, you will receive a JSON with the following format:
{
"access_token": "7032f1fd-e7a9-48bc-b9db-88a35b121b09!3964ab5e6ab7d771c6c5744122eaac8da2363a041fbfa96828441cd4a2b4c19d1319bb0dc775aa@SSORT!7032f1fd-e7a9-48bc-b9db-88a35b121b09!0c6fe15b76f14f5b8a0805c1b6c20appA",
"token_type": "Bearer",
"expires_in": 1800,
"refresh_token": "00167b653abbc064b5982a1fd15e0f974b5",
"scope": "gam_user_data",
"user_guid": "139f4332-3f40-47b0-8fb4-ee7b3dbddc4f"
}
To receive a refresh token, you must change the default value of the property Maximum OAuth token renewals in GAM Security Policies.
The endpoint is: https://<idp_domain>/<virtual_dir>/oauth/gam/userinfo.
GET
Headers:
Content-Type: Type of content that will be returned. Use application/x-www-form-urlencoded, required.
Authorization: access_token obtained in the Step 2, required.
POSTMAN Example:

Response:
In response, you will receive a JSON with the following format:
{
"guid":"139f4332-3f40-47b0-8fb4-ee7b3dbddc4f",
"username":"user",
"email":"user@example.com",
"verified_email":true,
"first_name":"user",
"last_name":"User",
"external_id":"",
"birthday":"2000-01-01",
"gender":"N",
"url_image":"https://",
"url_profile":"",
"phone":"+598",
"address":".",
"city":".",
"state":".",
"post_code":".",
"language":"Eng",
"timezone":".",
"CustomInfo":""
}
The endpoint is: https://<idp_domain>/<virtual_dir>/oauth/gam/access_token.
POST
Headers:
Content-Type: Type of content that will be returned. Use application/x-www-form-urlencoded
Body:
client_id: Client ID of the application, required.
client_secret: Client Secret of the application, required.
grant_type: must be "refresh_token.", required.
refresh_token: refresh_token received when requesting the access_token obtained in Step 2, required.
POSTMAN Example:


Response:
In response, you will receive a JSON with the following format:
{
"access_token": "85a3006c-0606-41d2-980e-223f88463ec2!b1b3e778247c870560d49d17ffd514a2a8467747208b1cf4a641780a267466bc65fba8034c9bbc",
"token_type": "Bearer",
"expires_in": 180,
"refresh_token": "002b9ec850f78b845d883779fa52c91a01",
"scope": "gam_user_data",
"user_guid": "139f4332-3f40-47b0-8fb4-ee7b3dbddc4f"
}
When to call the Refresh Token
When a Rest service is called and the access token has expired, 401 and Error 103 are returned. If this happens and there is a Refresh Token saved, it can be used as detailed above; otherwise, a new Access Token must be requested.
POSTMAN Example:

Response:
In response, you will receive a JSON with the following format:
{
"error": {
"code": "103",
"message": "Token expired, log in again."
}
}