Use nest-keycloak-connect with Client Id and Secret approach - nestjs

New to keycloak, was able to get access_token with Client Id and Secret setup as credentials for a client but backend side always gives me:
WARN [Keycloak] Cannot validate access token: Error: Grant validation failed. Reason: failed to load public key to verify token. Reason: Expected "jwk" to be an Object
Digged a bit into it and found that it tried to find a matching kid from the list of kids returned by the /auth/realms/myrealm/protocol/openid-connect/certs
Checked that the kid in the jwt.headers(from the access_token i passed) indeed does not exist in the kids list provided by the /auth/realms/myrealm/protocol/openid-connect/certs response.
Is there a way to add the kid into the list to make it available for on the nestjs backend?
What would be suggested here? Forget about this credentials type?
Thanks in advance, any suggestions would be appreciated.

Related

msal-node error trying to resolve endpoints

I have been using MSAL in my React app for some time with success. One of the tokens that my app requests is for scope 'https://management.core.windows.net/user_impersonation'. I have a nodeJS server that I want to push that token acquisition to so I installed msal-node (1.12.1) and tried using the OBO flow:
const pca = new msal.ConfidentialClientApplication({
auth: {
clientId: settings.config.azure.clientId,
clientSecret: settings.config.azure.clientSecret,
authority: "https://login.microsoftonline.com/<tenantid>",
knownAuthorities: ["https://login.microsoftonline.com/<tenantid>"],
}
});
const request = {
scopes: ['https://management.core.windows.net//user_impersonation'],
oboAssertion: <token_extracted_from_auth_header>
}
const response = await pca.acquireTokenOnBehalfOf(request);
return response.accessToken;
However the above code results in the following error:
ClientAuthError: endpoints_resolution_error: Error: could not resolve endpoints. Please check network and try again. Detail: ClientAuthError: openid_config_error: Could not retrieve endpoints. Check your authority and verify the .well-known/openid-configuration endpoint returns the required endpoints. Attempted to retrieve endpoints from: https://login.microsoftonline.com/tenantid/v2.0/.well-known/openid-configuration
If I visit the URL it complains about I do get back some metadata so not really sure why it is failing.
Anybody have a suggestion?
Also in regards to OBO flow:
For my nodeJS app I have added that permission to the required API list
I presume the oboAssertion field is the token that is passed to my nodeJS app by the client? I simply extracted it from the Auth header
The actual error message there means that the URL that we are trying to contact is wrong. And it is wrong https://login.microsoftonline.com/tenantid/v2.0/.well-known/openid-configuration returns an error.
A coorrect one is: https://login.microsoftonline.com/19d5f71f-6c9a-4e7f-b629-2b0c38f2b167/v2.0/.well-known/openid-configuration
Notice how I used an actual teanant_id there. You can get yours from the Azure Portal - it's the "directory id"
If your web api is single tenant, i.e. it is only meant for the people in 1 organization, then the is the tenant id of that organization. It is also known as "directory id". You get it from the Azure Portal.
However, if your api is multi-tenant, i.e. it's a bit more complicated, and the "correct" answer is to use the tenant id of the incoming assertion. It's the tid claim in it.

Setting additionalLoginParams with auth v2

I've followed this guide to configure access to my backend app, but I use Node backend and React frontend. However I'm unable to perform the step Configure App Service to return a usable access token. I get the error "Cannot execute the request for site x because the site is running on auth version v2.". To handle this I tried instead editing the sheet authsettingsV2, and I believe I found that the property properties.identityProviders.azureActiveDirectory.login.loginParameters in v2 equals properties.additionalLoginParams in v1 as editing this v2 property according to the tutorial shows the desired property in the v1 authsettings sheet.
However accessing my frontend app with this setting I get the error AADSTS901002: The 'resource' request parameter is not supported. before even being able to enter my credentials.
I've also tried without the additionalLoginParams setting completely, this gives me the error {"code":401,"message":"IDX10511: Signature validation failed. Keys tried: '[PII is hidden]'. \nkid: '[PII is hidden]'. \nExceptions caught:\n '[PII is hidden]'.\ntoken: '[PII is hidden]'."} on the API call, and upon inspecting my token, I find that the audience is the Microsoft Graph API. But I guess that is expected with this setup.
How can I proceed to enable access to my backend app? / How do I set the additionalLoginParams in auth version v2?
I am not sure if you have a correct access token. Please note that I am not talking about id token. Because from your response_type=code id_token, there should be only one id_token returned, but obviously the id_token cannot call your api, because what you need is an access token.
If you have not obtained a correct access token, then you should request an access token in the next step, refer to this link.
In addition, I must explain that all 401 errors are caused by api audiences. Therefore, make sure that your Application ID URI is set in the scope parameter.
When requesting an access token, you need to set the scope to: scope=openid api://{back-end api client id}/.default. Set response_type to: response_type=token.

Unable to generate a jwt token using DocuSign Python code

I am using docusign for digital signature , where I have to create a jwt token. For this I have been using code from git repo https://github.com/docusign/docusign-python-client.
docusign version 3.1.0 , python version 3.5 and 3.6 in sandbox mode .
getting following error
raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='https', port=443): Max retries exceeded with url http://account-d.docusign.com/oauth/token (Caused by NewConnectionError(': Failed to establish a new connection: [Errno -2] Name or service not known',))
i have followed the curl request using following url JSON Web Token (JWT) Grant
got an application token and while passing in auth giving me 401(401 UNAUTHORIZED
) error
postman
claim = {"iss": '4556e2f7-4a3d-41f9-a0c3-18535a28ab2a', "aud": 'account-d.docusign.com', "iat": now, "exp": later, "scope": " ".join(scopes)} token = jwt.encode(payload=claim, key=pkey, algorithm='RS256').decode("utf-8")
i getting application token using above code but when i pass all the required parameter i got {"error":"invalid_grant","error_description":"no_valid_keys_or_signatures"} but when i pasted my jwt token in jwt.io with my public and privte key its says signature verified.
I have added the links of screenshots, that might also help to understand more about the problem.
https://ibb.co/2yKXNCW https://ibb.co/cFTk6R1 https://ibb.co/t3YMkr2
The concept is to generate a key with 3 elements (Header RS256 Algorith, the Payload Data that contains the application date and token validity and the private and public key. On the site jwt.io we will put all this information and the site will retour an Base64 Key we can further entered on
Open the JWT.IO site jwt.io
Choose Algorithm RS256 on the top
For the second Pane : “Payload: Data”
https://admindemo.docusign.com/apps-and-keys
iss :
The integration key (also known as client ID) of the application.
sub : The User ID of the user to be impersonated.
(The person granting permission must have a DocuSign user account.)
The provided User ID must be in GUID (not email) format. You can look up a user’s GUID from their email using the users.list method.
Note: If you don’t already have the User ID of the user to act on behalf of, you can obtain it by completing the Authorization Code Grant flow begun in the Request the authorization code step.
https://admindemo.docusign.com/apps-and-keys -> Apps and Keys ->
aud : The URI of the authentication service instance to be used.
For demo environments, use account-d.docusign.com.
For production environments, use account.docusign.com.
Important: Do not include https:// in the aud value!
iat : The date-time when the JWT was issued
in Unix epoch format. You must include an iat value when creating a JWT, typically set to the current time.
You can convert a date to linux epoch format with the following link : https://www.epochconverter.com/
exp: The date-time when the JWT assertion will expire
in Unix epoch format. Defaults to one hour from the value of iat and cannot be set to a greater value. You must include an exp value when creating a JWT.
Use the epoch https://www.epochconverter.com/
⚠ Please note that this value must not be too far in time, in our example we are using 14 years of validity.
scope : The scopes to request. In our example “signature impersonation”.
All the scopes are defined on the following site https://developers.docusign.com/platform/auth/reference/scopes/
{
"iss":"ea670856-0422-4d8e-99bd-80560d323639",
"sub":"917c9fc5-d615-43bb-8a28-87e7ede3b8ac",
"aud":"account-d.docusign.com",
"iat": 1628496664,
"exp":1912493464,
"scope":"signature impersonation"
}
For the Pane “Verify Signature”
https://admindemo.docusign.com/apps-and-keys -> Actions -> Edit
… -> Click on “Generate RSA”
Select the Public and Paste it on the section
And make the same for the public key. If everything is OK, you must have the Tag “Signature Verified” at the left of the document, see the picture bellow.
For the final step, you obtain the key for stating using the API
Go to Postman
https://www.postman.com/use-cases/api-testing-automation/
Sign in (for me with my google account)
You must fille the following values
Select “Post”
Put the API Value : https://account-d.docusign.com/oauth/token
Click on the “Body” section
Add the key “grant_type”
Add the value “urn:ietf:params:oauth:grant-type:jwt-bearer” for the key “grant_type”
Add the key “assertion”
Add the generate value from the site jwt on the previous steps
Finally Click on Send for obtain the “access_token” necessary the the further call.
[enter image description here][1]
Here are the things that you must ensure:
You have an Integration key (clientID) that is configured correctly.
You have an RSA Private key. that key was copied/pasted exactly as given to your configuration file. New lines must be preserved
Your URLs are matching the environment. Meaning you use account-d and demo.docusign.net for the sandbox env endpoints.
You need the userId which is a GUid for the user that would be impersonated. That user must consent to the application. You have to ensure you pass userId and not accountId and that it is for the same account that you would be using.
If you confirm all of this and still get an error - I would consider to use our code example to start. I don't see code in your question, but our code example should be a good way to start.

"Bad Request" message in JWT OAuth authentication flow

i've followed all the instructions at the doc for generate JWT Token, but only receive "Bad Request" as response...
when i try to run eg-01-php-jwt the same occurs. i'm using DocuSign demo environment and simulating requests using Postman and curl
the steps i'm doing are:
generating authorization uri as https://account-d.docusign.com/oauth/auth?response_type=code&scope=signature%20impersonation&client_id=c0c3e3b4-87ec-46e6-afad-9f8cf9dda84c&redirect_uri=http://example.com/api/docusign/obtain-consent/callback
fill login and password for different docusign sandbox account
at the redirected uri i get the code parameter and decode at jwt.io, getting kid value from header
use kid value at sub to generate a new jwt token
sign jwt token with my private key
try to obtain access token and receive "Bad Request" as response message
my (updated) generated token is
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJpc3MiOiJjMGMzZTNiNC04N2VjLTQ2ZTYtYWZhZC05ZjhjZjlkZGE4NGMiLCJzdWIiOiI2ODE4NWZmMS00ZTUxLTRjZTktYWYxYy02ODk4MTIyMDMzMTciLCJpYXQiOjE1NTExMDA0MDksImV4cCI6MTU1MjEwMDQwOSwiYXVkIjoiYWNjb3VudC1kLmRvY3VzaWduLmNvbSIsInNjb3BlIjoic2lnbmF0dXJlIGltcGVyc29uYXRpb24ifQ.I1LhY77Rd0-op6UE3zUQvA5UxXIBzHUMyhhrwSN_TBv9ghiNAOr2aVz8Glf16bulkqSrE6A67h3DvL_VDm5NpNzcDQttjlf-CtlnBrjyt2w1niZkYnlmrUXW3SofDJkNHEj9-zQOa2XBrzTOLIhD6g2V0adBe45mwwGpMpOu0oPameUseDVEBeQ50mCZcyiMGYazEA0qeE9Ws9Rb7GxZxmOIZXaWirohmJhNfic5wHprJvA6tTwxai5-4xAwnhrjpsOWKoQRxXRkCKKcIIrKf8SEz4KOH2RCUBqMZRGys81CIDtowtLoDUeMCRKTaxnbrCFax4blJSZ8X3ptyneVpw
UPDATE # 2019-02-26:
to achieve what i want i needed to complete the authorization code flow, get the user account id from step 4 (retrieve user data) and finally generate the jwt token with that info as sub at payload!
That assertion previously only included the signature scope. JWT Authentication requires signature impersonation.
Now that that has been updated, there are a couple of other possible issues:
Invalid user ID. The JWT assertion requires an active User ID in the
sub field. If the user is closed or the ID is incorrect this will
fail.
Invalid signature. The JWT assertion must be signed with an RSA
private key associated with the iss / Client ID in use. If there
are any invalid/encoding characters or trailing spaces, the signature
may not be valid.
I'd recommend opening a case with DocuSign Support. On your side, you'll only receive the error invalid_grant. Support-side logging will have a more specific error. To assist with resolution, when opening a case please provide the following:
Integrator key
Demo account ID
JWT Assertion
x-DocuSign-TraceToken header value

Nodejs - ADAL package issue

I am using adal-node package in my Nodejs app for authenticating against Azure AD.
URL: https://www.npmjs.org/package/adal-node
I am using acquireTokenWithAuthorizationCode method to get the token and it works fine.
When my auth code expires, I want to refresh my token using the below.
authenticationContext.acquireTokenWithRefreshToken(_tokenData.refreshToken, authdata.clientId, authdata.resource, callback).
But when I run this code, its giving me the below error.
"Get Token request returned http error: 400 and server response: {"error":"invalid_request","error_description":"AADSTS90014: The request body must contain the following parameter: 'client_secret or client_assertion'
The method will not accept client secret as its argument, but still it complains that it needs a client secret.
Can you please help?
Thanks
Anil
Unfortunately, the library does not support your scenario right now. The function acquireTokenWithRefreshToken that you are using was intended for OAuth public clients that don't require a client secret, but your app is an OAuth confidential client which does.
I have filed the following issue in the GitHub repo to track the need to add a new method that would support your scenario.
https://github.com/AzureAD/azure-activedirectory-library-for-nodejs/issues/22

Resources