Using OAuth 2.0 for Server to Server Applications (Service Accounts)
A JWT is composed as follows:
{Base64url encoded header}.{Base64url encoded claim set}.{Base64url encoded signature}
The base string for the signature is as follows:
{Base64url encoded header}.{Base64url encoded claim set}
signing algorithm and the format of the assertion. In this case: RSA SHA-256 and JWT token format
{"alg":"RS256","typ":"JWT"}
params are:
Name | Description |
---|---|
iss | The email address of the service account |
scope | A space-delimited list of the permissions that the application requests |
aud | A descriptor of the intended target of the assertion. When making an access token request this value is always https://oauth2.googleapis.com/token |
exp | The expiration time of the assertion, specified as seconds since 00:00:00 UTC |
iat | The time the assertion was issued, specified as seconds since 00:00:00 UTC, January 1, 1970 |
{
"iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
"scope": "https://www.googleapis.com/auth/devstorage.read_only",
"aud": "https://oauth2.googleapis.com/token",
"exp": 1328554385,
"iat": 1328550785
}
To obtain an access token that grants an application delegated access to a resource, include the email address of the user in the JWT claim set as the value of the sub field.
Name | Description |
---|---|
sub | The email address of the user for which the application is requesting delegated access |
{
"iss": "761326798069-r5mljlln1rd4lrbhg75efgigp36m78j5@developer.gserviceaccount.com",
"sub": "some.user@example.com",
"scope": "https://www.googleapis.com/auth/prediction",
"aud": "https://oauth2.googleapis.com/token",
"exp": 1328554385,
"iat": 1328550785
}
The JWT claim set should be serialized to UTF-8 and Base64url-safe encoded
The input for the signature is the byte array of the following content:
{Base64url encoded header}.{Base64url encoded claim set}
The only signing algorithm supported by the Google OAuth 2.0 Authorization Server is RSA using SHA-256 hashing algorithm. This is expressed as RS256 in the alg field in the JWT header.
Sign the UTF-8 representation of the input using SHA256withRSA (also known as RSASSA-PKCS1-V1_5-SIGN with the SHA-256 hash function) with the private key obtained from the Google API Console. The output will be a byte array.
GenerateJWT( iss; scope; aud; pk )
GenerateJWT(
"YOUR_SERVICE_ACCOUNT_EMAIL";
"https://www.googleapis.com/auth/devstorage.read_only";
"https://oauth2.googleapis.com/token";
"YOUR_PRIVATE_KEY"
)
(CF) UnixTime()
(CF) Base64urlEncode(str)
- iss: The email address of the service account
- scope: A space-delimited list of the permissions that the application requests
- aud: A descriptor of the intended target of the assertion. When making an access token request this value is always https://oauth2.googleapis.com/token
- exp: The expiration time of the assertion, specified as seconds since 00:00:00 UTC
- iat: The time the assertion was issued, specified as seconds since 00:00:00 UTC, January 1, 1970
- sub: The email address of the user for which the application is requesting delegated access (only used for delegated access)
Let(
[
_ISS = iss;
_SCOPE = scope;
_AUD = aud;
_PRIVATE_KEY = pk;
_TOKEN_TTL = 3600;
_UTC_ZERO = UnixTime();
header = JSONSetElement ( "{}";
["alg"; "RS256"; JSONString];
["typ"; "JWT"; JSONString] );
claimSet = JSONSetElement ( "{}";
["iss"; _ISS; JSONString];
["scope"; _SCOPE; JSONString];
["aud"; _AUD; JSONString];
["iat"; _UTC_ZERO ; JSONNumber];
["exp"; _UTC_ZERO + _TOKEN_TTL; JSONNumber] );
signatureData = "" & Base64urlEncode ( header ) & "." & Base64urlEncode ( claimSet ) & "";
signature = CryptGenerateSignature ( signatureData ; "SHA256" ; _PRIVATE_KEY ; "" );
signedJWTData = signatureData & "." & Base64urlEncode (signature )
];
signedJWTData
)
Just returns the seconds since 00:00:00 UTC
Floor( GetAsNumber ( Get ( CurrentTimeUTCMilliseconds ) ) / 1000 ) - GetAsNumber ( Timestamp ( "01/01/1970" ; "00:00:00" ) )
Does a "url safe" Base64 Encoding, accordingly to RFC4648 https://tools.ietf.org/html/rfc4648 Do not use simple Base64 native encodings from FileMaker.
Let (
_e=Base64EncodeRFC(4648 ;data );
Substitute( _e;["+";"-"];["/";"_"];["\r";""];["\n";""];["=";""] )
)
Basicaly pass the JWT body to the authentication server as:
$ASSERTION = GenerateJWT( iss; scope; aud; pk )
$GRANT_TYPE = "urn:ietf:params:oauth:grant-type:jwt-bearer"
Post a CURL to the token_uri: https://oauth2.googleapis.com/token with the cURL options:
CURL -X POST -d "grant_type=$GRANT_TYPE&assertion=$ASSERTION"
The result contains your authorization token, expiration date time or error messages if request fails.
Hi, your explanation is what I need for a JWT signature that I have to establish.
One question: the Base64urlEncode function is depreciated in FileMaker 18 and 19 --> do I use instead the Base64EncodeRFC(4648 ;data ) as you described? (when I use the debugger on jwt.io it keep mentioning that the signature is wrong)