To successfully authenticate a service (server side) to connect (as a
service client) to another service protected by an access token, you will need to implement OAuth
this way.
Before you begin:Before you begin, you must have an account with an OpenID
Connect/OAuth2 provider that will provide authentication services for you.
Service-to-service
– also known as "machine-to-machine" – implementation may vary depending on the IdP; refer to the
IdP documentation for more information.
You must have packaged your applications and services
into a Genero Archive. You create a Genero Archive (.gar) with fglgar
gar. For more information about packaging a Genero Archive, refer to the Deploying
apps with Genero Archive pages in the Genero Application Server User Guide.
You will
need your GAS running.
About this task:The access token got from
the Identity Provider (IdP) to check access to the service is also required to access the client
service.
Steps
-
On the IdP site, register your Genero application.
Single sign-on implementation may vary depending on the IdP; refer to the IdP documentation
for more information.
-
Register the web application.
-
Register the GAS delegation service oauth2callback URL
Typically, the oauth2callback redirect URL is the URL of the OpenIDConnect service on the GAS
where the IdP will redirect the user-agent to get the OAuth2 ID token. For more information on the
callback URL, go to
SSO oauth2callback redirect URL
The provider provides the CLIENT_PUBLIC_ID
and
CLIENT_SECRET_ID
that you use for requesting access tokens to the protected
resources.
-
Determine which single sign-on protocol the IdP uses: OpenID Connect or OAuth2. If the IdP is
using the OAuth2 protocol, you will need to register the IdP's OAuth2 endpoints in the GAS.
Go to
Import IdP metadata as OAuth2 for instructions on importing the metadata
in the GAS. For details about the ImportOAuth tool, go to
ImportOAuth.
Important:
If the IdP is using the OpenID Connect protocol, there is no need to use the
ImportOAuth program as OpenID Connect has the metadata feature that allows
Genero's OpenID Connect service to automatically fetch the metadata, including all the endpoint
URLs, from the IdP.
-
Configure your Genero web application xcf file for delegation to the
IdP.
Add the
DELEGATE
element and set its
service
attribute to
the Genero OpenIDConnectServiceProvider. Provide the URL of the IdP and the
CLIENT_PUBLIC_ID
and
CLIENT_SECRET_ID
tokens obtained when
registering your application.
<APPLICATION Parent="defaultwa" ...>
<EXECUTION>
#...
</PATH>
</MODULE>
<DELEGATE service="services/OpenIDConnectServiceProvider">
<IDP>my_OAuth_provider_url</IDP>
<SCOPE>email</SCOPE>
<CLIENT_PUBLIC_ID>XXXXXXXX.apps.myOAUTHIdpusercontent.com</CLIENT_PUBLIC_ID>
<CLIENT_SECRET_ID>XXXXXX-XXXXXX</CLIENT_SECRET_ID>
</DELEGATE>
#...
</EXECUTION>
</APPLICATION>
The configuration differs slightly depending on the Single sign-on
protocol used by the IdP.
-
Deploy and enable your application on the GAS using a Genero Archive file.
Your gar file must have a MANIFEST file pointing to your application
configuration file (.xcf).
-
Deploy the gar file on the GAS.
Use the gasadmin tool; for example, gasadmin gar --deploy-archive
myAppGar.gar
-
Enable the application on the GAS
Use the gasadmin tool; for example, gasadmin gar --enable-archive
myAppGar.gar
Test your application by starting the GAS and entering the application URL in the browser. If
your browser is redirected to the IdP to enter your credentials, you have configured your
application correctly. If your credentials are valid, your browser is redirected back to the
application; otherwise an HTML error page is returned.
Web service
-
On the IdP site, register the scopes for the service or APIs providing the service.
Typically, it consists of the following tasks:
-
Register the web service with the IdP.
-
Register all the scopes (permissions) that might be granted to the client.
These are the scopes you should already have defined in your web service 4GL with the
WSScope
attribute to provide security globally for the service (on the
WSInfo
record) or for its functions. You should have a list of such
WSScope
entries.
For more information about WSScope
and how it
is implemented in a Genero REST web service, refer to the Handling security section and
the WSScope topic in the Genero Business Development Language User Guide.
-
Register the GAS delegation service oauth2callback URL
Typically, the oauth2callback redirect URL is the URL of the OpenIDConnect service on the GAS
where the IdP will redirect the user-agent to get the OAuth2 ID token. For more information on the
callback URL, go to
SSO oauth2callback redirect URL
-
Configure your web service xcf file for delegation to the IdP.
In the
DELEGATE
element set the
service
attribute to the
Genero GeneroAccessService, and provide the URL of the IdP in the
IDP
element.
<APPLICATION Parent="ws.default" ...>
<EXECUTION>
</ENVIRONMENT_VARIABLE>
</PATH>
</MODULE>
<DELEGATE service="services/GeneroAccessService">
<IDP>my_OAuth_provider_url</IDP>
</DELEGATE>
#...
</EXECUTION>
</APPLICATION>
GeneroAccessService
is the REST web service in the
$FGLDIR that handles delegation in the service calls, and forwards the access
token if used in a call to another service.
-
Deploy and enable your service on the GAS using a Genero Archive file.
Your gar file must have a MANIFEST file pointing to your web service
configuration file (.xcf).
-
Deploy the gar file on the GAS.
Use the gasadmin tool; for example, gasadmin gar --deploy-archive
myServiceGar.gar
-
Enable the service on the GAS
Use the gasadmin tool; for example, gasadmin gar --enable-archive
myServiceGar.gar
-
Generate the stub for your 4GL client.
-
Get an access token from the IdP to access the web service.
Use the GetToken tool. For further information on using
GetToken, go to GetToken.
Line breaks have been added to the command example to improve
readability.
fglrun GetToken password -u user -p mypw
--idp https://my_OAuth_provider.oauth.com
--savetofile mytoken.json myWSScope
Where:
- The password command is used to get an access token on behalf of an
authenticated user.
- The user name and password provided (
-u user -p mypw
) is that of a registered
user in the IdP.
- The URL of the IdP is specified in the
--idp
option.
- mytoken.json is the filename where the access token is saved.
myWSScope
is the list of scopes (permissions) that should be granted to the
client for the service or services required in the token.
You get an access token that is valid for 10 minutes. After ten minutes, you will need to query
for a new access token.
-
If your GAS is not running, start it.
Test to ensure you can access the web service, by entering its URL in your browser, adding the
token obtained in the previous step in the
query:
http://myhost:6394/gas/ws/r/myGroup/myXcf/myService?openapi.json&access_token=token
If you can see the OpenAPI documentation displayed, you have accessed the protected
service.
-
Generate the stub.
Use the fglrestful tool.
For more details on using the fglrestful tool, refer to the
fglrestful page in the Genero Business Development Language User Guide
For example, from the web service URL (line breaks have been added to improve
readability)
fglrestful -o clientStub --oauth yes --tokenfile mytoken.json
http://myhost:6394/gas/ws/r/myGroup/myXcf/myService?openapi.json
Where:
- clientStub specifies the filename of the stub in the output
(
-o
) option.
--oauth yes
specifies that the web service is secured by an IdP and code to
handle OAuth access is generated in the stub.
--tokenfile
specifies mytoken.json as the file where the
token was saved in the previous step.
- The URL of the web service is specified with the query string ?openapi.json
to get the documentation file.
The clientStub.4gl is generated from the OpenAPI document. It contains the
code to manage calls made by client applications to the web service resources and from the web
service to a client service, if that is also required by the service. You need to compile it and
import the module into your Genero REST client application.
-
Create your Genero REST client application.
For more details on calling a web service through a client application, refer to the
Calling a web service function section in the Genero Business Development Language User Guide.
Write code in your 4gl module:
-
Import the stub file module.
-
Import the
OAuthAPI
library.
-
In the MAIN program block, code to retrieve the IdP IDs – provided via the GAS environment at
runtime – and initiate OAuth.
Important: Initiate OAuth firstCall the OAuthAPI.init()
function to register the access token and access information (such as subject, scopes, endpoints,
and so on.) with the GWS engine before making any calls to the service functions.
IMPORT FGL clientStub
IMPORT FGL OAuthAPI
DEFINE c_client_id STRING
DEFINE c_secret_id STRING
DEFINE my_user_id STRING
MAIN
# Init OAuthAPI
LET c_client_id = fgl_getenv("OIDC_CLIENT_ID")
LET c_secret_id= fgl_getenv("OIDC_SECRET_ID")
IF NOT OAuthAPI.Init(5, c_client_id, c_secret_id) THEN
DISPLAY "Error: unable to initialize OAuth"
EXIT PROGRAM 1
ELSE
LET my_user_id = OAuthAPI.getIDSubject
END IF
# ... calls to web service functions
END MAIN
Troubleshooting access
- If errors are encountered accessing your service, check the logs:
vm-services-GeneroAccessService*.log, and the
AccessService.log:
For instance, if you get error 403 "Forbidden" and you
see the following message in the
AccessService.log:
ERROR : 29389 - [AccessService] "RetrieveIDPMetadata" INSERT failed :UNIQUE constraint failed: fjs_provider.issuer
Check
that the IdP's URL in the
DELEGATE
element of your web service
xcf is correct.
- If a call made to a Genero web service function fails, check the error status code returned to
the client. For example, a value of -1 indicates a failed operation. The code
-15553
with a description such as Asynchronous Connection failed
or connection timeout expired
indicates an infrastructure error. Check
that you have a call to OAuthAPI.init()
in your client application, as shown in the
Create client application
step.
For more information on handling errors, refer to the Handle REST server
errors page in Genero Business Development Language User Guide