Docusign and service Authentication : invalid request - node.js

I am trying to use service authentication mechanism for logging in. But getting an invalid request.I have created the JWT using node jsonwebtoken package.below is the error I am getting.
Copying the JWt creation logic
var jwt = require('jsonwebtoken');
var fs = require('fs');
//creating the payload for docusign
var payload = {
"iss": "cb91877d-1d55-48ae-88d7-fd215c4fe2ca",
"sub": "6cd4ea4e-3e68-4994-88b1-a321847cbf7e",
"iat": 1508868716,
"exp": 1508869916,
"aud": "account-d.docusign.com",
"scope": "signature",
"nbf":1508868716,
"name": "neeush"
}
var cert = fs.readFileSync('private.pem'); // get private key
var token = jwt.sign(payload, cert, { algorithm: 'RS256'});
Can you find any issues in the same.
enter image description here

var jwt = require('jsonwebtoken');
var fs = require('fs');
//creating the payload for docusign
var payload = {
"iss": "cb91877d-1d55-48ae-88d7-fd215c4fe2ca",
"sub": "6cd4ea4e-3e68-4994-88b1-a321847cbf7e",
"iat": 1509096042,
"exp": 1509099042,
"aud": "account-d.docusign.com",
"scope": "signature impersonation",
"name" :"name value" //not required
}
var cert = fs.readFileSync('private.pem'); // get private key
var token = jwt.sign(payload, cert, { algorithm: 'RS256'});
console.log(token)
console.log('---------------------------------------------------');
//printing the token to a file
fs.writeFile('jwttoken.txt', token, function (err) {
if (err)
return console.log(err);
});
When the this generated token is used able to get post correct.
Earlier the token was printed on th console and copied from there which was creating the problem.
#Larry K Thanks for the help with the scope claim.

Remove nbf and name claims.
Change scope claim to "signature impersonation"
See https://docs.docusign.com/esign/guide/authentication/oa2_jwt.html#creating-the-jwt-token

Related

Firebase LoginWithCustomToken throws error

I am creating firebase custom token with jsonwebtoken in nodejs and once token created and passing to the firebase.auth().signInWithCustomToken(token) return error message says as below
the custom token format is incorrect. please check the documentation.
private_key:"-----BEGIN PRIVATE KEY-----\n*****\n-----END PRIVATE KEY-----\n"
stored the private_key in fb-private-secret.key file
Note:-- along with \n as I have got in ServiceAccountKey.json file from the firebase.
**Sample code:-**
const jwt = require("jsonwebtoken");
const fb_private_key = fs.readFileSync('./fb-private-secret.key').toString().replace(/\\n/gm, '\n');
in Nodejs express :-
const token = jwt.sign({
"iss": "https://securetoken.google.com/****",
"sub": user.uid,
"aud": "banded-totality-****",
"iat": new Date().getTime(),
"exp": new Date().getTime()+(60*60*24*5)*1000,
"uid":user.uid
},fb_private_key,{header:{kid:'#####' }, algorithm:'RS256' });
In Reactjs Front-End:-
//token which i get from the server.
const {user} = await firebase.auth().signInWithCustomToken(token);
At the above line (signInWithCustomToken) error comes says
the custom token format is incorrect. please check the documentation.
Any help would be appreciated.
Thanks
To sign in with a custom token, must be generated with the correct properties. Specifically:
alg: "RS256"
aud: "https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit"
Update
Admin SDK solution:
const admin = require('firebase-admin');
const credentials = require('./credentials.json');
admin.initializeApp({
credential: admin.credential.cert(credentials)
});
// example of claims
const additionalClaims = {
premium: true
}
admin.auth().createCustomToken("user_id_goes_here", additionalClaims)
.then((customToken )=> {
console.log(customToken);
})
.catch(console.error);

DocuSign Get JWT Token MEAN Stack

Building a basic application where users can find Service Providers using MEAN Stack, and after negotiations are over, agreements are auto generated and have to be signed by both parties.
Got Stuck on generation of JWT Token for authentication.
Steps I followed are:
Generate a url for obtaining consent from user and pass it to frontend. Users will be redirected and permissions can be granted from there.
var url = "https://account-d.docusign.com/oauth/auth?response_type=code&scope=signature&client_id=42017946-xxxx-xxxx-xxxx-81b0ca97dc9a&redirect_uri=http://localhost:4200/authorization_code/callback";
res.status(200).json({
status: 1,
message: 'Fetched',
value: url
});
After successful redirection with code in URL, API call is made to backend for the generation of JWT token.
Token is generated as follows:
var jwt = require('jsonwebtoken');
var privateKey = fs.readFileSync(require('path').resolve(__dirname, '../../src/environments/docusign'));
const header = {
"alg": "RS256",
"typ": "JWT"
};
const payload = {
iss: '42017946-xxxx-xxxx-a5cd-xxxxxx',
sub: '123456',
iat: Math.floor(+new Date() / 1000),
aud: "account-d.docusign.com",
scope: "signature"
};
var token = jwt.sign(payload, privateKey, { algorithm: 'RS256', header: header });
Private key used above is from docusign admin panel.
iss -> Integration key against my app.
sub -> user id in the drop down of user symbol in admin panel
Obtain the access token
const axios = require('axios');
axios.post('https://account-d.docusign.com/oauth/token',
{
grant_type: "urn:ietf:params:oauth:grant-type:jwt-bearer",
assertion: token
})
.then(resposne => {
console.log(response);
})
.catch(err => {
if (err.response) {
console.log(err);
} else if (err.request) {}
else {}
})
But I am constantly getting error: { error: 'invalid_grant', error_description: 'no_valid_keys_or_signatures' }
I would suggest using the node.JS SDK or npm package and using the build-it JWT method to authenticate. The code would look like this:
(click here for GitHub example)
DsJwtAuth.prototype.getToken = async function _getToken() {
// Data used
// dsConfig.dsClientId
// dsConfig.impersonatedUserGuid
// dsConfig.privateKey
// dsConfig.dsOauthServer
const jwtLifeSec = 10 * 60, // requested lifetime for the JWT is 10 min
scopes = "signature", // impersonation scope is implied due to use of JWT grant
dsApi = new docusign.ApiClient();
dsApi.setOAuthBasePath(dsConfig.dsOauthServer.replace('https://', '')); // it should be domain only.
const results = await dsApi.requestJWTUserToken(dsConfig.dsClientId,
dsConfig.impersonatedUserGuid, scopes, rsaKey,
jwtLifeSec);
const expiresAt = moment().add(results.body.expires_in, 's').subtract(tokenReplaceMin, 'm');
this.accessToken = results.body.access_token;
this._tokenExpiration = expiresAt;
return {
accessToken: results.body.access_token,
tokenExpirationTimestamp: expiresAt
};

how to do i get user id from JWT token? [duplicate]

I tried to get user id from a JWT token. I got a JWT token and sucessfully verified it, but it doesn't return an id.
When I decode the JWT:
const decoded = jwt.verify(token, config.get('jwtPrivateKey'));
var userId = decoded.id
console.log(decoded)
I got this output:
{ iat: 1561463667 }
But I excepted this output:
id :"*****************"
How do I get the user id from the token?
When the whole output is { iat: 1561463667 }, it means, that no extra payload/claims were added when the token was signed.
The jsonwebtoken package usually adds iat (issuedAt, the time when the token was issued) as a default claim.
In simple words: you can only decode claims, that were added before.
To add more claims, try this code (when you're in control of the code which issues the token):
let payload = { "id" : "1"};
let token = jwt.sign( payload,'secret', { noTimestamp:true, expiresIn: '1h' });
Here I added an expiry time (exp), and set the option noTimestamp to suppress the automatically added iat claim.
The result looks like this:
{
"id": "1",
"exp": 1561471747
}
and the token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjEiLCJleHAiOjE1NjE0NzI0MzV9.jmKyITRoxLl0fy0-rrwgPOA_iRgGQu8W4Cc6dPupOMA
Then you can get the id as you have already shown in your question:
const decoded = jwt.verify(token, "your secret or key");
var userId = decoded.id
console.log(userId)
You can also paste the above shown JWT or your token into the https://jwt.io debugger, to inspect the token and see the structure and the actual claim names. Maybe there's no id, but a userId or similar, or a subclaim, which is a registerd claim name to be used to identify the principal:
The "sub" (subject) claim identifies the principal that is the
subject of the JWT.
It might also happen, that the token contains nested objects, e.g.:
{
"user_data":
{
"user_id": "1",
"user_name: "superuser"
},
"exp": 1561471747
}
then you get the user_id this way:
const decoded = jwt.verify(token, "your secret or key");
var userId = decoded.user_data.user_id
console.log(userId)

How to get user id using jwt token

I tried to get user id from a JWT token. I got a JWT token and sucessfully verified it, but it doesn't return an id.
When I decode the JWT:
const decoded = jwt.verify(token, config.get('jwtPrivateKey'));
var userId = decoded.id
console.log(decoded)
I got this output:
{ iat: 1561463667 }
But I excepted this output:
id :"*****************"
How do I get the user id from the token?
When the whole output is { iat: 1561463667 }, it means, that no extra payload/claims were added when the token was signed.
The jsonwebtoken package usually adds iat (issuedAt, the time when the token was issued) as a default claim.
In simple words: you can only decode claims, that were added before.
To add more claims, try this code (when you're in control of the code which issues the token):
let payload = { "id" : "1"};
let token = jwt.sign( payload,'secret', { noTimestamp:true, expiresIn: '1h' });
Here I added an expiry time (exp), and set the option noTimestamp to suppress the automatically added iat claim.
The result looks like this:
{
"id": "1",
"exp": 1561471747
}
and the token:
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjEiLCJleHAiOjE1NjE0NzI0MzV9.jmKyITRoxLl0fy0-rrwgPOA_iRgGQu8W4Cc6dPupOMA
Then you can get the id as you have already shown in your question:
const decoded = jwt.verify(token, "your secret or key");
var userId = decoded.id
console.log(userId)
You can also paste the above shown JWT or your token into the https://jwt.io debugger, to inspect the token and see the structure and the actual claim names. Maybe there's no id, but a userId or similar, or a subclaim, which is a registerd claim name to be used to identify the principal:
The "sub" (subject) claim identifies the principal that is the
subject of the JWT.
It might also happen, that the token contains nested objects, e.g.:
{
"user_data":
{
"user_id": "1",
"user_name: "superuser"
},
"exp": 1561471747
}
then you get the user_id this way:
const decoded = jwt.verify(token, "your secret or key");
var userId = decoded.user_data.user_id
console.log(userId)

JWT Claims lost when running App Service in Azure

Recently implemented Asp.net core 2.0 WEB Api. Works smashingly on my local dev environment. HOWEVER ... when i deploy to AZURE i find that my JWT Access Token does NOT contain the Issuer and Audience claims and therefore i get the 401 Unauthorized with : Bearer error="invalid_token", error_description="The audience is invalid". The JWT generated on my local machine has : (courtesy of jwt.io)
{
"http://schemas.xmlsoap.org/...": "Rory#gspin.com",
"sub": "Rory#gspin.com",
"given_name": "Rory",
"family_name": "McGilroy",
"email": "Rory#gspin.com",
"jti": "3875f83d-eb93-4d45-8507-795a0cb7e3e4",
"iat": 1533506381,
"rol": "api_access",
"id": "420990b2-4747-4c3c-ae0f-ccbbc4dfe521",
"nbf": 1533506381,
"exp": 1533513581,
"iss": "gspin.com",
"aud": "https://www.gspin.com"
}
But after deploying same application to AZURE APP Service my Access Token contains the following:
{
"http://schemas.xmlsoap.org/...": "billyttom#fido.com",
"sub": "billyttom#fido.com",
"given_name": "billy mark tom",
"family_name": "last",
"email": "billyttom#fido.com",
"jti": "0d34a03f-31ae-45aa-9ace-004d5916b430",
"iat": 1533498384,
"rol": "api_access",
"id": "5485d641-974b-4f60-ade6-35c048503701",
"nbf": 1533498383,
"exp": 1533505583
}
Missing iss and aud???
Any idea why these are being dropped when deployed to azure when they are defined and present in Token generated on local machine/Visual Studio env?
My Code is : public async Task<string> GenerateEncodedToken(string
userName, ClaimsIdentity identity, UserManager<GSIdentityUser> _userManager)
{
var user = await _userManager.FindByNameAsync(userName);
var userClaims = await _userManager.GetClaimsAsync(user);
var claims = new[]
{
new Claim(ClaimTypes.Name, userName),
new Claim(JwtRegisteredClaimNames.Sub, userName),
new Claim(JwtRegisteredClaimNames.GivenName, user.FirstName),
new Claim(JwtRegisteredClaimNames.FamilyName, user.LastName),
new Claim(JwtRegisteredClaimNames.Email, user.Email), /// same as username
new Claim(JwtRegisteredClaimNames.Jti, await _jwtOptions.JtiGenerator()), // the uniqueness claim is a GUID
new Claim(JwtRegisteredClaimNames.Iat, ToUnixEpochDate(_jwtOptions.IssuedAt).ToString(), ClaimValueTypes.Integer64),
identity.FindFirst(Helpers.Constants.Strings.JwtClaimIdentifiers.Rol),
identity.FindFirst(Helpers.Constants.Strings.JwtClaimIdentifiers.Id)
};
// Create the JWT security token and encode it.
var jwt = new JwtSecurityToken(
issuer: _jwtOptions.Issuer,
audience: _jwtOptions.Audience,
claims: claims,
notBefore: _jwtOptions.NotBefore,
expires: _jwtOptions.Expiration,
signingCredentials: _jwtOptions.SigningCredentials);
var encodedJwt = new JwtSecurityTokenHandler().WriteToken(jwt);
return encodedJwt;
}
public ClaimsIdentity GenerateClaimsIdentity(string userName, string id)
{
return new ClaimsIdentity(new GenericIdentity(userName, "Token"), new[]
{
new Claim(Helpers.Constants.Strings.JwtClaimIdentifiers.Id, id),
new Claim(Helpers.Constants.Strings.JwtClaimIdentifiers.Rol, Helpers.Constants.Strings.JwtClaims.ApiAccess)
});
}
Also in ConfigureServices i have :
services.Configure<JwtIssuerOptions>(options =>
{
options.Issuer = Configuration["JwtIssuerOptions:Issuer"];
options.Audience=Configuration["JwtIssuerOptions:Audience"];
options.SigningCredentials = new SigningCredentials(_signingKey,
SecurityAlgorithms.HmacSha256);
});

Resources