How to get user information using node oidc provider - node.js

I got access token and I will pass access_token to userinfo endpoint it throwing an invalid token provided error How to fix this Issue. I tried to debug why this error is throwing we have validateAccessToken method(userinfo.js) in this method check the access_token is exist or not exist using this code await ctx.oidc.provider.AccessToken.find(accessTokenValue); when i print this result it's showing undefined
oidc_configuration.js
const oidc = new Provider('http://localhost:3000', {
clients: [
{
client_id: 'oidcCLIENT',
client_secret: '...',
grant_types: ['refresh_token', 'authorization_code'],
redirect_uris: ['http://sso-client.dev/providers/7/open_id', 'http://sso-client.dev/providers/8/open_id'],
}
],
interactions: {
url(ctx, interaction) { // eslint-disable-line no-unused-vars
return `/api/v1/open_id/interaction/${interaction.uid}`;
},
},
cookies: {
keys: ['some secret key', 'and also the old rotated away some time ago', 'and one more'],
},
claims: {
address: ['address'],
email: ['email', 'email_verified'],
phone: ['phone_number', 'phone_number_verified'],
profile: ['birthdate', 'family_name', 'gender', 'given_name', 'locale', 'middle_name', 'name',
'nickname', 'picture', 'preferred_username', 'profile', 'updated_at', 'website', 'zoneinfo'],
},
features: {
devInteractions: { enabled: false }, // defaults to true
deviceFlow: { enabled: true }, // defaults to false
revocation: { enabled: true }, // defaults to false
},
jwks: {
keys: [
{
d: 'VEZOsY07JTFzGTqv6cC2Y32vsfChind2I_TTuvV225_-0zrSej3XLRg8iE_u0-3GSgiGi4WImmTwmEgLo4Qp3uEcxCYbt4NMJC7fwT2i3dfRZjtZ4yJwFl0SIj8TgfQ8ptwZbFZUlcHGXZIr4nL8GXyQT0CK8wy4COfmymHrrUoyfZA154ql_OsoiupSUCRcKVvZj2JHL2KILsq_sh_l7g2dqAN8D7jYfJ58MkqlknBMa2-zi5I0-1JUOwztVNml_zGrp27UbEU60RqV3GHjoqwI6m01U7K0a8Q_SQAKYGqgepbAYOA-P4_TLl5KC4-WWBZu_rVfwgSENwWNEhw8oQ',
dp: 'E1Y-SN4bQqX7kP-bNgZ_gEv-pixJ5F_EGocHKfS56jtzRqQdTurrk4jIVpI-ZITA88lWAHxjD-OaoJUh9Jupd_lwD5Si80PyVxOMI2xaGQiF0lbKJfD38Sh8frRpgelZVaK_gm834B6SLfxKdNsP04DsJqGKktODF_fZeaGFPH0',
dq: 'F90JPxevQYOlAgEH0TUt1-3_hyxY6cfPRU2HQBaahyWrtCWpaOzenKZnvGFZdg-BuLVKjCchq3G_70OLE-XDP_ol0UTJmDTT-WyuJQdEMpt_WFF9yJGoeIu8yohfeLatU-67ukjghJ0s9CBzNE_LrGEV6Cup3FXywpSYZAV3iqc',
e: 'AQAB',
kty: 'RSA',
n: 'xwQ72P9z9OYshiQ-ntDYaPnnfwG6u9JAdLMZ5o0dmjlcyrvwQRdoFIKPnO65Q8mh6F_LDSxjxa2Yzo_wdjhbPZLjfUJXgCzm54cClXzT5twzo7lzoAfaJlkTsoZc2HFWqmcri0BuzmTFLZx2Q7wYBm0pXHmQKF0V-C1O6NWfd4mfBhbM-I1tHYSpAMgarSm22WDMDx-WWI7TEzy2QhaBVaENW9BKaKkJklocAZCxk18WhR0fckIGiWiSM5FcU1PY2jfGsTmX505Ub7P5Dz75Ygqrutd5tFrcqyPAtPTFDk8X1InxkkUwpP3nFU5o50DGhwQolGYKPGtQ-ZtmbOfcWQ',
p: '5wC6nY6Ev5FqcLPCqn9fC6R9KUuBej6NaAVOKW7GXiOJAq2WrileGKfMc9kIny20zW3uWkRLm-O-3Yzze1zFpxmqvsvCxZ5ERVZ6leiNXSu3tez71ZZwp0O9gys4knjrI-9w46l_vFuRtjL6XEeFfHEZFaNJpz-lcnb3w0okrbM',
q: '3I1qeEDslZFB8iNfpKAdWtz_Wzm6-jayT_V6aIvhvMj5mnU-Xpj75zLPQSGa9wunMlOoZW9w1wDO1FVuDhwzeOJaTm-Ds0MezeC4U6nVGyyDHb4CUA3ml2tzt4yLrqGYMT7XbADSvuWYADHw79OFjEi4T3s3tJymhaBvy1ulv8M',
qi: 'wSbXte9PcPtr788e713KHQ4waE26CzoXx-JNOgN0iqJMN6C4_XJEX-cSvCZDf4rh7xpXN6SGLVd5ibIyDJi7bbi5EQ5AXjazPbLBjRthcGXsIuZ3AtQyR0CEWNSdM7EyM5TRdyZQ9kftfz9nI03guW3iKKASETqX2vh0Z8XRjyU',
use: 'sig',
}, {
crv: 'P-256',
d: 'K9xfPv773dZR22TVUB80xouzdF7qCg5cWjPjkHyv7Ws',
kty: 'EC',
use: 'sig',
x: 'FWZ9rSkLt6Dx9E3pxLybhdM6xgR5obGsj5_pqmnz5J4',
y: '_n8G69C-A2Xl4xUW2lF0i8ZGZnk_KPYrhv4GbTGu5G4',
},
],
},
});
// Heroku has a proxy in front that terminates ssl, you should trust the proxy.
oidc.proxy = true;
const callback = oidc.callback();
How to fix this issue

You're running without a persistent adapter, meaning an in-memory one is used, are you possibly restarting your server after receiving the access token before calling the userinfo endpoint?

After completing the authentication, you will get access_token as well as id_token. I think you were using id_token in place of access_token which is why you are seeing that error
Instead use access_token then you can see the details

Related

Implement OAuth Implicit Flow in NestJS Swagger

Using the Swagger module provided from NestJS there is no functionality to implement an OAuth connection that automatically get the user token through implicit flows.
From the website there is a lack of documentation about oauth.
https://docs.nestjs.com/openapi/security.
The solution that I've found is using this piece of code
const config = new DocumentBuilder()
.setTitle('Swagger API')
.setVersion('1.0')
.addSecurity('ApiKeyAuth', {
type: 'apiKey',
in: 'header',
name: 'token',
})
.addBearerAuth()
.addOAuth2(
{
type: 'oauth2',
flows: {
implicit: {
tokenUrl: `${configSv.get("OAUTH_DOMAIN")}/oauth/token`,
authorizationUrl: `${configSv.get("OAUTH_DOMAIN")}/authorize`,
scopes: {"read:products": null, "read:properties": null, "read:categories": null, openid: null, profile: null, email: null},
},
},
},
)
.build();
But doesn't retrieve correctly the token and scopes aren't working, facing a 403 error calling the endpoints

NodeJS OIDC Provider getting aud and resource server errors upgrade from 6.x to 7.x

I am trying to upgrade [node-oidc-provider]https://github.com/panva/node-oidc-provider from version 6.x to version 7.x. I am using the authorization code flow for a React application.
I am getting an error regarding aud(audience) being a required field for JWT tokens:
Error: JWT Access Tokens must contain an audience, for Access Tokens without audience (only usable at the userinfo_endpoint) use an opaque format
Looking at the code and documentation, I tried to update the aud field by defining a function in formats.jwt.customizers.
I am not sure if this is the right solution as after doing that, I faced an issue regarding invalid resource server configuration:
Error: invalid Resource Server jwt configuration
Below is my existing configuration (provided file is support/configuration.js):
module.exports = {
clients: [
{
"application_type": "web",
"grant_types": [
"authorization_code"
],
"id_token_signed_response_alg": "RS256",
"post_logout_redirect_uris": [
"http://localhost:3001"
],
"require_auth_time": false,
"response_types": [
"code"
],
"subject_type": "public",
"token_endpoint_auth_method": "none",
"introspection_endpoint_auth_method": "none",
"revocation_endpoint_auth_method": "none",
"request_uris": [],
"client_id_issued_at": 1622600472.0,
"client_id": "my_client_id",
"client_name": "Sample client application",
"client_secret_expires_at": 0.0,
"client_secret": "my_client_secret" ,
"redirect_uris": [
"http://localhost:3001/callback"
],
"client_background_uri": "/public/img/default.png",
"app_id": "sample_app"
}
],
clientBasedCORS: (ctx, origin, client)=>{
return true
},
interactions: {
url(ctx, interaction) { // eslint-disable-line no-unused-vars
return `/interaction/${interaction.uid}`;
},
},
cookies: {
keys: ['some secret key', 'and also the old rotated away some time ago', 'and one more'],
},
formats:{
AccessToken :'jwt',
customizers: { jwt: async(ctx, token, jwt)=>{
jwt.payload.aud = jwt.payload.iss
}}
},
claims: {
address: ['address'],
email: ['email', 'email_verified'],
phone: ['phone_number', 'phone_number_verified'],
profile: ['birthdate', 'family_name', 'gender', 'given_name', 'locale', 'middle_name', 'name',
'nickname', 'picture', 'preferred_username', 'profile', 'updated_at', 'website', 'zoneinfo'],
},
features: {
devInteractions: { enabled: false }, // defaults to true
resourceIndicators: {
enabled: true,
async useGrantedResource(ctx) {
return ctx.oidc.body && ctx.oidc.body.usegranted;
},
getResourceServerInfo(ctx, resource) {
if (resource.includes('wl')) {
return {
audience: resource,
scope: 'api:read api:write',
};
}
throw new errors.InvalidTarget();
},
defaultResource(ctx) {
if (ctx.oidc.body && ctx.oidc.body.nodefault) {
return undefined;
}
return 'urn:wl:default';
},
},
deviceFlow: { enabled: true }, // defaults to false
revocation: { enabled: true }, // defaults to false
},
jwks: {
keys: [/* keys left out for privacy*/]
},
};
This is working with me using resourceIndicators configuration that looks like:
resourceIndicators: {
enabled: true,
getResourceServerInfo: async (ctx, resourceIndicator, client) => {
return {
scope: 'api:read api:write',
audience: resourceIndicator,
accessTokenTTL: 2 * 60 * 60, // 2 hours
accessTokenFormat: 'jwt',
jwt: {
sign: { alg: 'RS256' },
},
}
}

How to push transaction EOS Blockchain (eosjs - unsatisfied_authorization)?

I use Anchor Wallet.
This is init code
const privateKeys = ["myprivatekey"];
const signatureProvider = new JsSignatureProvider(privateKeys);
const rpc = new JsonRpc(config.mainnet, { fetch });
const api = new Api({ rpc, signatureProvider, textDecoder: new TextDecoder(), textEncoder: new TextEncoder() });
return {rpc, api};
Then i try to push transaction
const transaction = await api.transact({
actions: [{
account: 'eosio',
name: 'buyrambytes',
authorization: [{
actor: 'username',
permission: 'active',
}],
data: {
payer: 'username',
receiver: 'username',
bytes: 8192,
},
}]
}, {
blocksBehind: 3,
expireSeconds: 30,
});
(docs example)
and receive error
details: [
{
message: `transaction declares authority '{"actor":"username","permission":"active"}', but does not have signatures for it.`,
file: 'authorization_manager.cpp',
line_number: 643,
method: 'get_required_keys'
}
],
json: {
code: 401,
message: 'UnAuthorized',
error: {
code: 3090003,
name: 'unsatisfied_authorization',
what: 'Provided keys, permissions, and delays do not satisfy declared authorizations',
details: [Array]
}
}
}
Maybe i enter wrong private key (Anchor -> Export private key -> Copy key) or something else, idk.
All other functions (for exampe get_block etc.) works fine
try with owner:
authorization: [{
actor: 'username',
permission: 'owner',
}],

How to prevent overloading JWT token

i'm using jwt token with node.js npm jsonwebtoken in order to manage my users authentication. above that i'm adding to the payload the user permissions which contains the user read and write to which section.
like so:
const payload = {
user: {
id: user.id,
permissions: user.account_permissions
}
};
jwt.sign(
payload,
config.get('jwtSecret'),
{ expiresIn: TIME},
(err, token) => {
if (err) throw err;
res.json({ token });
}
);
The account_permissions object looks somthing like that:
const permissions = {
platform: 'Management',
sections: [
{
sectionName: 'setup',
read: true,
write: true
},
{
sectionName: 'chat',
read: true,
write: true
},
{
sectionName: 'maintenence',
read: true,
write: true
},
{
sectionName: 'classes',
read: true,
write: true
},
{
sectionName: 'income',
read: true,
write: true
},
{
sectionName: 'announcements',
read: true,
write: true
},
{
sectionName: 'messages',
read: true,
write: true
}
],
school: shoolID
};
My question is ; every user can have many permissions objects to different platforms which in that case makes the jwt token to be very large (sometimes to big to be even sent in the header).
I have a middleware that checks the user permissions in every route, im trying to avoid saving that data in a database in order to save database calls. how can i avoid such an overloading.

Amazon Cognito - AdminCreateUser - how to not skip email verification

I am using Amazon Cognito user pool and AdminCreateUser api to create a new user so that we don't allow users to sign themselves up. It works great but it seems that email verification step is being skipped so when making an api call, I needed to set email_verified attribute to true to make reset password flow to work.
Can I make email verification to happen before sending out an inviatation email?
const params = {
DesiredDeliveryMediums: ['EMAIL'],
UserAttributes: [
{
Name: 'email',
Value: email
},
{
Name: 'email_verified',
Value: 'True'
},
],
Username: email,
UserPoolId: userPoolId,
}
cognitoIdentityService.adminCreateUser(params, function(err, data) {
// ...
To prevent backend to send verification email, set MessageACtion="SUPPRESS"
response = client.admin_create_user(
UserPoolId='USER_POOL_ID',
Username='USERNAME',
TemporaryPassword='PASSWORD',
UserAttributes=[
{
'Name': 'email',
'Value': 'email#example.com'
},
{
'Name': 'email_verified',
'Value': 'true'
}
],
MessageAction='SUPPRESS'
)

Resources