Mission statement.Nihil novi sub sole, the WWW is not a very safe place. Thus this is paramount to protect the public API endpoints from unauthorised access. In Hardening access to Kyma APIs with JWT tokens I demonstrated how to protect public Kyma APIs with JWT tokens, using SAP BTP XSUAA as OIDC provider. But sometimes, if on-premise or edge application needed to call into a protected Kyma API, a self-generated JWT might be a simpler approach.... Let's see how this can be done... |
Step1. | Generate a digitally signed JWT token |
Step2. | Create an API Rule. |
Step3 and Step4 | Test (bootstrap) the API. |
const cert = '-----BEGIN CERTIFICATE-----\nMIIFGzCCAwMCBGBb1dwwDQYJKoZIhvcNAQELBQAwUjELMAkGA1UEBhMCVVMxDDAK\nBgNVBAoMA1NBUDEVMBMGA1UECwwMY
.........truncated.........................
URdaHVX6B270SUDiP6TDPApn9E+IaISzPRpk\nXT6c0QNVYg37DBU/qhSN\n-----END CERTIFICATE-----\n';
const key = '-----BEGIN PRIVATE KEY-----\nMIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDFz/eQv30tj5oC\nLjT1Im7OtVAVo6mB/wQbEpbOh3LSI
.........truncated.........................
LSxBTGdiZznqgLKnImxU1WDSA2xlKJy7J\nAwx8lLYgANSJ7qkKPgPR/t5ZHrx/plY=\n-----END PRIVATE KEY-----\n';
const jwt = require('jsonwebtoken');
const { randomUUID } = require('crypto'); // Added in: node v14.17.0
function generateAccessToken(issuer, jwks_uri) {
return jwt.sign( {iss: issuer, jti: randomUUID() }, key, { algorithm: 'RS256', keyid: 'QtV2kV6VfnvJpRHCHFVXjDPFKydXWVHjuz4XIE0xxxx', header: {jku: jwks_uri}, expiresIn: '3600sec' } );
}
Issuer URL |
|
JWKS URI URL |
|
{"error":{"code":401,"status":"Unauthorized","request":"<request>","message":"The request could not be authorized"}}
const axios = require('axios')
const jwt = require('jsonwebtoken');
//The url is the JWT-protected API Rule enpoint
//The logonToken is the self-generated bearer JWT token
try {
logonToken = generateAccessToken(
'http://poster-app.default.svc.cluster.local',
'http://poster-app.default.svc.cluster.local/jwks_uri'
);
let decoded = await jwt.decode(logonToken, { complete: true });
console.log('decoded logonToken:', decoded);
let configGet = {
method: 'get',
url: url,
headers: {
"Authorization": 'Bearer ' + logonToken,
}
};
const response = await axios(configGet);
console.log(response.status);
return response.data;
}
catch(error) {
console.log(error);
return error;
};
curl -ik https://<hostname>.<domain>/here_location?location=Massy -H 'Authorization: Bearer eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHBzOi8vb2VtLWF6dXJlLmF1dGhlbnRpY2F0aW9uLmFwMjEuaGFuYS5vbmRlbWFuZrsKGSwfr6KoREMSrJ7wxp80NgoFFqD8CS2lK4OSoXmIQqWJsRZzCHfa-rKA'
HTTP/2 200
{
"items": [
{
"title": "Massy, Île-de-France, France",
"id": "here:cm:namedplace:20004823",
"resultType": "locality",
"localityType": "city",
"address": {
"label": "Massy, Île-de-France, France",
"countryCode": "FRA",
"countryName": "France",
"stateCode": "IDF",
"state": "Île-de-France",
"county": "Essonne",
"city": "Massy",
"postalCode": "91300"
},
]
}
{
"keys": [
{
"kid": "QtV2kV6VfnvJpRHCHFVXjDPFKydXWVHjuz4XIE0xxx",
"kty": "RSA",
"alg": "RS256",
"use": "sig",
"n": "xc_3kL99LY-aAi409SJuzrVQFaOpgf8EGxKWzody0iPIf39NH8CzCf7kN52B4sKrBJU7ygNIdAebZu_cP2dRQcf7646q2yr0BBVUP8x92FRL
...................................................(truncated)..................................
RsaXQ6T6RNJTmk1FpFpgI2wO_gtaRSdVxA1cMpzvfsfiDhK-gEDDhoYQCYWzsL-X_0",
"e": "AQAB",
"x5c": [
"MIIFGzCCAwMCBGBb1dwwDQYJKoZIhvcNAQELBQAwUjELMAkGA1UEBhMCVVMxDDAKBgNVBAoMA1NBUDEVMBMGA1UECwwMYXRl
...................................................(truncated)..................................
9934p3PLnZAJOhLJO0X6cHCFbMC+6GxXTdisQVivIOKUURdaHVX6B270SUDiP6TDPApn9E+IaISzPRpkXT6c0QNVYg37DBU/qhSN"
],
"x5t": "DQMOdr9ITZxhd6NYI7l8y6LIdTw",
"x5t#S256": "NINub7bHeCqT1mEJiQcUdbJtJgSmTeQhw48DGAJ1r1w"
}
]
}
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.
User | Count |
---|---|
24 | |
22 | |
16 | |
12 | |
9 | |
9 | |
8 | |
8 | |
8 | |
8 |