"Bad Request" message in JWT OAuth authentication flow - docusignapi

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

Related

How to verify signature of refreshed id_token in Azure active directory

We are using Azure active directory Oauth code flow to authenticate the user.
We got the access_token, id_token and refresh_token using code(got it on redirect URL).
We are using id_token to authorization each request after successful authentication and we can verify JWT using the public key which we got from /discovery/v2.0/keys api.
Now, JWT will expire after 1 hour. so we need to refresh this id_token.
I am refreshing id_token using below cURL
curl --request POST \
--url https://login.microsoftonline.com/{tenant_id}/oauth2/token \
--header 'Content-Type: application/x-www-form-urlencoded' \
--data 'client_id=client%20id&refresh_token=refesh%20token%20&grant_type=refresh_token&client_secret=client_secret&scope=openid
In the response of this API, we got the access_token, refresh_token, id_token, but if you observe id_token, it does not contain JWT signature (the third part of JWT), without signature we can not verify JWT
We can not find any document reference why id_token is not having a signature part.
Is there any other way to refresh id_token?
Is there any workaround if id_token can not be refreshed?
In some cases an Id token may be returned without a signature, especially if it is acquired through a back-channel with a client secret.
You already are getting the token through an encrypted channel, from the authority.
If someone was able to inject something there, they would be able to direct your app's requests for OpenID metadata as well, replacing the signing keys your app expects.
Thus the signature would not add much value here.
In addition, you won't send the Id token to any API as Id tokens should not be used for authorization.
That's what access tokens are for :)
The OpenID Connect spec has this to say: https://openid.net/specs/openid-connect-core-1_0.html#IDTokenValidation
If the ID Token is received via direct communication between the Client and the Token Endpoint (which it is in this flow), the TLS server validation MAY be used to validate the issuer in place of checking the token signature. The Client MUST validate the signature of all other ID Tokens according to JWS [JWS] using the algorithm specified in the JWT alg Header Parameter. The Client MUST use the keys provided by the Issuer.
But then, interestingly mentions this as well: https://openid.net/specs/openid-connect-core-1_0.html#IDToken
ID Tokens MUST be signed using JWS and optionally both signed and then encrypted using JWS and JWE respectively, thereby providing authentication, integrity, non-repudiation, and optionally, confidentiality, per Section 16.14. If the ID Token is encrypted, it MUST be signed then encrypted, with the result being a Nested JWT, as defined in [JWT]. ID Tokens MUST NOT use none as the alg value unless the Response Type used returns no ID Token from the Authorization Endpoint (such as when using the Authorization Code Flow) and the Client explicitly requested the use of none at Registration time.
So.. it could be that Azure AD is not compliant with spec?
EDIT: The v1 endpoint of Azure AD is not compliant in this regard. The newer v2 endpoint is fully OpenID Connect compliant.

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.

JWT Issue with Docusign API

We generated JWT using docusign given private key and validated by Docusign public key in jwt.io site. It generated valid signature.
Using same signature we called Docusign demo server for access token
POST https://account-d.docusign.com/oauth/token
with
grant_type=urn:ietf:params:oauth:grant-type:jwt-bearer
assertion=Signature generated
but getting error "Invalid Grant".
What could be the possible reason? If signature is already verified in jwt.io with public key, Docusign should accept the assertion value.
As documented, you also need to supply the following claims:
iss--The integration key (also known as client ID) of the application.
sub--The user ID of the user to be impersonated.
iat--The DateTime when the JWT was issued, in Unix epoch format.
exp--The DateTime when the JWT assertion will expire, in Unix epoch format. Use 1 hour after iat or less.
aud--domain name of the authentication service instance to be used. For demo environments, use account-d.docusign.com For production environments, use account.docusign.com. Note: Do not include https:// in the aud value!
scope--The scopes being requested. For the JWT bearer grant, the requested scope should be signature.
See the docs and also see the DocuSign JWT code examples, the repos named eg-01-*
Ask a new question if you'd like further help.

How to check error when validating jwt token using validate-jwt (Previously: How to use a custom built jwt in validate-jwt?)

I try to limit access to a REST API using a JWT token using the validate-jwt policy. Never did that before.
Here's my inbound policy (taken from the point Simple token validation here):
<validate-jwt header-name="Authorization" require-scheme="Bearer">
<issuer-signing-keys>
<key>{{jwt-signing-key}}</key>
</issuer-signing-keys>
<audiences>
<audience>CustomerNameNotDns</audience>
</audiences>
<issuers>
<issuer>MyCompanyNameNotDns</issuer>
</issuers>
</validate-jwt>
Using this generator I created a claim (I'm not sure whether I understood issuer and audience correctly):
{
"iss": "MyCompanyNameNotDns",
"iat": 1572360380,
"exp": 2361278784,
"aud": "CustomerNameNotDns",
"sub": "Auth"
}
In the section Signed JSON Web Token I picked Generate 64-bit key from the combo box. The key that was generated I put in the place of {{jwt-signing-key}}.
Now, I'm trying to call the API using Postman. I add an "Authorization" header, and as the value I put "Bearer {{ JWT created by the linked generator }}".
I get 401, JWT not present. What am I doing wrong?
According to my research, If you use HS256 signing algorithms, the key must be provided inline within the policy in the base64 encoded form. In other words, we must encode the key as base64 string. For more details, please refer to the document
My test steps are as below
Create Jwt token
Test
a. If I directly provide the key in the policy, I get the 401 error
b. If I encode the key as base64 string in the policy, I can call the api
Jim Xu's answer to encode the key as base64 string in the policy allowed me to get this far :-)
I set the Ocp-Apim-Trace parameter to true in order to debug it more closely. I followed the link provided in the response under ocp-apim-trace-location, and in the "on error" section I found the following message:
JWT Validation Failed: IDX10225: Lifetime validation failed. The token is missing an Expiration Time. Tokentype: 'System.IdentityModel.Tokens.Jwt.JwtSecurityToken'..
Which is funny, because I have set the Expiration Time... to 2099.
I changed it to a month from now and it worked just fine.

auth0 invite-only application JWT not appended at the end of redirect url

I'm following this guide, but at the user activation step after successful email verification, the jwt token was not appended as shown here, but I got some other metadata instead:
http://localhost:3000/onboarding?supportSignUp=true&supportForgotPassword=true&email=mail%40test.com&message=Your%20email%20was%20verified.%20You%20can%20continue%20using%20the%20application.&success=true#
I'm using express and the auth0 nodejs api.
You need to add the generated JWT yourself in the result_url.
This code uses API v2 to create a new email verification ticket. It is specifying the result_url argument as the local /Account/Activation action handler. And it is putting the generated JWT token as part of the query string.
After the user verifies his o her email address (in Auth0), he will be redirected to the result_url endpoint, with the token in the query string (/Account/Activation?userToken=xxxx in the sample). This piece of code handles that endpoint, verifying the token received and showing a view that allows the user to enter his password and POST the final activation (handled here).

Resources