How to configure extraQueryParameters for redirect request in MSAL.js - azure-ad-b2c

My react app uses MSAL (#azure/msal-browser) for user authentication, so I configure MSAL instance in my index.tsx using configuration object:
const config = {
clientId: "myAppId",
msalConfig: {
auth: {
authority: "signUpSignInCustomPolicyURI",
clientId: "myAppId",
knownAuthorities: ["myB2CTenant.b2clogin.com"],
redirectUri: "/"
},
cache: {<cacheconfig>}
},
loginScopes: ['openid', 'offline_access'],
authorities: {
signUpSignIn: "signUpSignInCustomPolicyURI",
forgotPassword: "forgotPasswordCustomPolicyURI",
}
}
msalInstance = new PublicClientApplication(config);
Then I wrap my app component in MsalProvider component:
<MsalProvider instance={msalInstance}>
<App/>
</MsalProvider>
and use <MsalAuthenticationTemplate> in protected components so users are prompted to login automatically.
On the other hand, we have an ability to add extra parameters to RequestRedirect like this:
const { instance } = useMsal();
const loginRedirectRequest = {
scopes: <myLoginScopes>,
extraQueryParameters: {
locale: "localeId",
theme: "themeId"
}
};
instance.loginRedirect(loginRedirectRequest);
My question is how to configure MSAL instance so it would apply extraQueryParameters every time it redirects users automatically?

Add it into the MSAL config object to start with.
const config = {
clientId: "myAppId",
msalConfig: {
auth: {
authority: "signUpSignInCustomPolicyURI",
clientId: "myAppId",
knownAuthorities: ["myB2CTenant.b2clogin.com"],
redirectUri: "/"
},
cache: {<cacheconfig>}
},
loginScopes: ['openid', 'offline_access'],
authorities: {
signUpSignIn: "signUpSignInCustomPolicyURI",
forgotPassword: "forgotPasswordCustomPolicyURI",
},
extraQueryParameters: {
locale: "localeId",
theme: "themeId"
}
}
msalInstance = new PublicClientApplication(config);

Related

Octokit.js github base url setup

I am trying to authenticate with my enterprise github through App in octokit.js but I couldn't find any parameter to change gihub url. Can someone please help?
const {Octokit, App} = require('octokit')
// below points to github.com
const app = new App({ appId: appId1, privateKey: privateKey1 })
// below does not work
//const app = new App({ appId: appId1, privateKey: privateKey1 , baseUrl: mygitHub })
app.octokit.rest.apps.getAuthenticated();
Using nodejs.
Found answer at https://github.com/octokit/app.js/#constructor
const { Octokit } = require("#octokit/core");
new App({
appId: 123,
privateKey: "-----BEGIN PRIVATE KEY-----\n...",
oauth: {
clientId: 123,
clientSecret: "secret",
},
webhooks: {
secret: "secret",
},
Octokit: Octokit.defaults({
baseUrl: "https://ghe.my-company.com/api/v3",
}),
});

Why does nodemailer throw the error: Invalid credentials? [duplicate]

I would like to find a way to send email from my app using nodemailer to the users either with some kind of google authentication or any other way. Below mentioned working code has stopped working after Google has disabled less secure app option.
const nodemailer = require('nodemailer')
const sendEmail = async options => {
const transporter = nodemailer.createTransport({
// host: "smtp.gmail.com",
// port: "465",
// secure: true,
service:'gmail',
auth: {
user: "USER_EMAIL",
pass: "USER_PASSWORD"
},
tls:{rejectUnauthorized:false}
})
const message = {
from: `${process.env.FROM_NAME} <${process.env.FROM_EMAIL}>`,
to: options.email,
subject: options.subject,
text: options.message,
html: options.message,
attachments: [
{
filename: '.png',
path: __dirname + '.png',
cid: '.png'
}
]
}
const info = await transporter.sendMail(message)
console.log('Message sent : %s', info.messageId)
console.log(__dirname)
}
module.exports = sendEmail
At the time of writing, Less Secure Apps is no longer supported by google. And you can't use your google account password.
You're gonna have to generate a new app password.
App passwords only work if 2-step verification is turned on.
Follow this steps to get the app password
Go to https://myaccount.google.com/security
Enable 2FA
Create App Password for Email
Copy that password (16 characters) into the pass parameter in Nodemailer auth.
const client = nodemailer.createTransport({
service: "Gmail",
auth: {
user: "username#gmail.com",
pass: "Google-App-Password-Without-Spaces"
}
});
client.sendMail(
{
from: "sender",
to: "recipient",
subject: "Sending it from Heroku",
text: "Hey, I'm being sent from the cloud"
}
)
You should check out Xoauth2.
Nodmailer supports serval types of Oauth
let transporter = nodemailer.createTransport({
host: "smtp.gmail.com",
port: 465,
secure: true,
auth: {
type: "OAuth2",
user: "user#example.com",
clientId: "000000000000-xxx0.apps.googleusercontent.com",
clientSecret: "XxxxxXXxX0xxxxxxxx0XXxX0",
refreshToken: "1/XXxXxsss-xxxXXXXXxXxx0XXXxxXXx0x00xxx",
accessToken: "ya29.Xx_XX0xxxxx-xX0X0XxXXxXxXXXxX0x",
expires: 1484314697598,
},
});

TS - NodeMailer OAuth2 'auth' does not exist in type 'TransportOptions

I have a problem. I need to make email sending function with Gmail api. In docs it tells me to make a createTransport function like this:
const transport = nodemailer.createTransport({
service: "gmail",
auth: {
type: "OAuth2",
user: "horvatlucian1#gmail.com",
clientId: CLIENT_ID,
clientSecret: CLIENT_SECRET,
refreshToken: REFRESH_TOKEN,
accessToken: accessToken,
},
})
DOCS
But it all turns red and returns:
Error
Any solution? Thanks.
There is a problem of type script when you tring to pass the accessToken because in google oauth2client the return type of getAccessToken() is https://github.com/googleapis/google-auth-library-nodejs/blob/b0ddb7512fb9ed1e51b6874b7376d7e1f26be644/src/auth/oauth2client.ts#L331
that not supported by the types of nodemailer that should be string:
https://github.com/DefinitelyTyped/DefinitelyTyped/blob/7827d853a1d623dd5345d9a11ced3e15eb5d3d8b/types/nodemailer/lib/xoauth2.d.ts#L24
by looking at the return type of the getAccessToken you can see that the token is inside that have type string so to fix that just destructure your token from the accessToken.
const transport = nodemailer.createTransport({
service: "gmail",
auth: {
type: "OAuth2",
user: "horvatlucian1#gmail.com",
clientId: CLIENT_ID,
clientSecret: CLIENT_SECRET,
refreshToken: REFRESH_TOKEN,
accessToken: accessToken.token,
},
})
1/
const transport = nodemailer.createTransport({
service: String("gmail") || "",
auth: {
type: String("OAuth2"),
user: String(SENDER_MAIL),
clientId: String(CLIENT_ID),
clientSecret: String(CLIENT_SECRET),
refreshToken: String(REFRESH_TOKEN),
access_token: String(access_token),
},
});
and the ERRO WITH MSG :
[ERROR] 14:02:23 тип Unable to compile TypeScript:
server/config/sendmail.ts(25,7): error TS2769: No overload matches this call.
The last overload gave the following error.
Argument of type '{ service: string; auth: { type: string; user: string; clientId:string; clientSecret:string; refreshToken:string; access_token:GetAccessTokenResponse; }; }' is not assignable to parameter of type 'TransportOptions | Transport<unknown>'.
Object literal may only specify known properties, and 'service' does not exist in type 'TransportOptions | Transport<unknown>'.
The accessToken required in nodemailer.createTransport is nullable
Because of that, to avoid error, you must cover the case when accessToken is null by providing an empty string or something similar to avoid null error
const transport = nodemailer.createTransport({
service: 'gmail',
auth: {
type: 'OAuth2',
user: process.env.EMAIL_ADDRESS,
clientId: process.env.CLIENT_ID,
clientSecret: process.env.CLIENT_SECRET,
refreshToken: process.env.REFRESH_TOKEN,
accessToken: accessToken.token || '',
},
})
Hopefully that help

How to get the Authorization code in the node OIDC provider

I implemented node-OIDC-Provider in Node JS I got Id-token but I need authorize-code. So, when I hit this Api(http://localhost:3000/auth?client_id=oidcCLIENT&response_type=code&scope=openid&redirect_uri=http://localhost:3000) it throwing an error('http://localhost:3000/?error=invalid_request&error_description=Authorization%20Server%20policy%20requires%20PKCE%20to%20be%20used%20for%20this%20request'). How to fix this error and get the authorization code
Sample.js
const { Provider } = require('oidc-provider');
var express = require('express')
var app = express()
const oidc = new Provider('http://localhost:3000', {
clients: [
{
client_id: 'oidcCLIENT',
client_secret: '...',
grant_types: ['refresh_token', 'authorization_code'],
redirect_uris: ['http://localhost:3000'],
}
],
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'],
},
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',
},
],
},
});
// express/nodejs style application callback (req, res, next) for use with express apps, see /examples/express.js
app.get('/sample', function (req, res) {
res.send('hello world')
})
app.use(oidc.callback())
// or just expose a server standalone, see /examples/standalone.js
const server = app.listen(3000, () => {
console.log('oidc-provider listening on port 3000, check http://localhost:3000/.well-known/openid-configuration');
});
How to set authorization server policy in the OIDC using node(Authorization Server policy requires PKCE to be used for this request')
I believe you need to set these options:
pkce: {
required: true
},
token_endpoint_auth_method: "none"
Also, if using PKCE, you should be sending the standard code_challenge and code_verifier methods as in steps 4 and 8 of my blog post.

jwt config secret file push on git

I work on an node, express mongoose API with JWT (json web token). I don't push my config.js file to keep secret my key (.gitignore -> config.js) but when travis run my test with mocha it return the error : Cannot find module './config'.
I try to mock it but it doesn't work, so :
I can push my config.js file, it's not unsafe ?
How can i mock my require dependency config.js ?
You should push config.js in repo. But you should make it like this:
/*jshint esversion: 6 */
'use strict';
module.exports = function () {
return {
SERVER_HOST: process.env.HOST,
OTP: {
LENGTH: 6,
DURATION: 300000, //ms
},
TWILIO: {
ACCOUNT_SID: process.env.TWILIO_ACCOUNT_SID,
AUTH_TOKEN: process.env.TWILIO_AUTH_TOKEN,
MESSAGE_FROM: process.env.TWILIO_MESSAGE_FROM
},
JWT: {
SECRET: process.env.JWT_SECRET,
ALGORITHM: 'HS512',
ISSUER: 'GOHAN'
},
BCRYPT: {
SALT_ROUNDS: 10
},
EMAIL: {
USER: process.env.EMAIL_USER,
PASSWORD: process.env.EMAIL_PASSWORD
},
REDIS: {
HOST: process.env.REDIS_HOST,
PORT: process.env.REDIS_PORT
},
AWS: {
ACCESS_KEY_ID: process.env.AWS_ACCESS_KEY_ID,
SECRET_ACCESS_KEY: process.env.AWS_SECRET_ACCESS_KEY,
S3: {
PROFILE_PIC_BUCKET: process.env.AWS_S3_PROFILE_PIC_BUCKET,
VOICE_MESSAGES_BUCKET: process.env.AWS_S3_VOICE_MESSAGES_BUCKET,
REGION: process.env.AWS_S3_REGION,
SIGNED_URL_EXPIRY: 900
}
},
TCP_SERVER: {
PASSWORD: process.env.TCP_SERVER_PASSWORD
},
GOOGLE_API_KEY: process.env.GOOGLE_API_KEY,
APN: {
CONNECTION: {
production: (process.env.NODE_ENV === 'production'),
cert: process.env.APN_CERT,
passphrase: process.env.APN_PASSPHRASE,
key: process.env.APN_CERT
},
FEEDBACK: {
address: process.env.APN_FEEDBACK_ADDRESS,
cert: process.env.APN_CERT,
key: process.env.APN_CERT,
passphrase: process.env.APN_PASSPHRASE,
interval: process.env.APN_INTERVAL,
batchFeedback: process.env.APN_BATCHFEEDBACK
}
},
FCM: {
API_KEY: process.env.FCM_API_KEY,
RETRY_LIMIT: 3
}
};
};
All the code should be independent of the environment, this is the purpose of environment variables. Not to ensure safety.
You can load up the environment variables before running your app.
You can have different .env files for testing, dev and prod environments also.
EDIT:
The above config.js is from a project of mine.

Resources