#azure/msal-browser untrusted_authority error - reactjs

I've been trying to follow this tutorial...
Sign In Users From A React SPA
but I cannot get it to work. I have a personal azure account and have created an SPA application within Azure Active Directory to get a client id.
From everything I've read it says I should use https://login.microsoftonline.com/{tenant-id-here} as my authority but when I do I get the error...
ClientConfigurationError: untrusted_authority: The provided authority is not a trusted authority
I have tried adding a knownAuthorities parameter to the config, although I don't think I should have to as I'm just concerned with a single tenant.
When I do add the knownAuthorities param, the error changes to...
ClientAuthError: openid_config_error: Could not retrieve endpoints.
My config file looks like this
export const msalConfig = {
auth: {
clientId: '{client id from Azure AD Application}',
authority: 'https://login.microsoftonline.com/{tenant-id}',
redirectUri: 'http://localhost:3000',
},
cache: {
cacheLocation: "sessionStorage",
storeAuthStateInCookie: false
}
}
The sign in button that causes the error looks like this...
function handleLogin(instance) {
instance.loginPopup(loginRequest).catch(e => {
console.error(e);
})
}
function SignInButton() {
const {instance} = useMsal();
return (
<Button variant="secondary" className="ml-auto" onClick={() => handleLogin(instance)}>
Sign in
</Button>
)
}
Might I be missing something in the azure settings? Or something else in the react application itself?
UPDATE: 16/02/22
Well I've now got it working. I accidentally had the sign in button rendered inside an <a> tag, which must have been stopping the Microsoft login popup from loading. Probably trying to redirect somewhere, which prevented the MSAL process from finishing. Wasn't the most helpful error message to go on.
So to confirm, for a single tenant solution, you only need clientId and authority. And authority is definitely https://login.microsoftonline.com/{your-tenant-id}

I took a look on Github and the settings are a bit different. Try using "https://login.microsoftonline.com/common" as the authority:
const msalConfig = {
auth: {
clientId: "enter_client_id_here",
authority: "https://login.microsoftonline.com/common",
knownAuthorities: [],
cloudDiscoveryMetadata: "",
redirectUri: "enter_redirect_uri_here",
postLogoutRedirectUri: "enter_postlogout_uri_here",
navigateToLoginRequestUrl: true,
clientCapabilities: ["CP1"]
},
cache: {
cacheLocation: "sessionStorage",
storeAuthStateInCookie: false,
secureCookies: false
},
system: {
loggerOptions: {
loggerCallback: (level: LogLevel, message: string, containsPii: boolean): void => {
if (containsPii) {
return;
}
switch (level) {
case LogLevel.Error:
console.error(message);
return;
case LogLevel.Info:
console.info(message);
return;
case LogLevel.Verbose:
console.debug(message);
return;
case LogLevel.Warning:
console.warn(message);
return;
}
},
piiLoggingEnabled: false
},
windowHashTimeout: 60000,
iframeHashTimeout: 6000,
loadFrameTimeout: 0,
asyncPopups: false
};
}
const msalInstance = new PublicClientApplication(msalConfig);
source: https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-browser/docs/configuration.md

Kindly add the knownAuthorities, and it's worked for my sample
const msalConfig = {
auth: {
clientId: 'enter_client_id_here',
// comment out if you use a multi-tenant AAD app
authority: 'https://login.microsoftonline.com/{tenant-id}',
knownAuthorities: ["login.microsoftonline.com"],
redirectUri: 'http://localhost:8080'
}
};

Related

Need to differentiate login callback credentials from google and facebook using next-auth

I am getting data successfully from google and facebook login using next-auth. I want to save separate profiles for Google and Facebook as well. Data I am getting is name, image, email and session expiry but I need to differentiate the callback data. Maybe a provider name would work. I have tried to add provider in session and use it in page but in vain
Here is code for pages/api/auth/[...nextauth].js
import NextAuth from "next-auth"
import GoogleProvider from "next-auth/providers/google";
import FacebookProvider from "next-auth/providers/facebook";
export default NextAuth({
// Configure one or more authentication providers
providers: [
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID,
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
authorization: {
params: {
prompt: "consent",
access_type: "offline",
response_type: "code"
}
}
}),
FacebookProvider({
clientId: process.env.FACEBOOK_CLIENT_ID,
clientSecret: process.env.FACEBOOK_CLIENT_SECRET
})
],
jwt: {
encryption: true
},
secret: process.env.SECRET,
callback: {
async jwt({ token, account }) {
// Persist the OAuth access_token to the token right after signin
if (account) {
token.accessToken = account.access_token;
}
if (account?.provider) {
token.provider = account.provider;
}
return Promise.resolve(token);
},
async session({ session, token }) {
// Send properties to the client, like an access_token from a provider.
session.accessToken = token.accessToken;
session.provider = token.provider;
return Promise.resolve(session);
},
// redirect: async(url, _baseUrl) => {
// if (url === "/profile") {
// return Promise.resolve("/");
// }
// return Promise.resolve("/");
// }
}
})
Here is code for login page
const {data:session} = useSession();
{JSON.stringify(session, 4)};
Result I get is
{"user":{"name":"myname","email":"myemail","image":"myimage"},"expires":"2022-09-04T16:40:10.809Z"};

Store and authenticate FB/Google users from NextAuth to another backend api in Nextjs

I'm using Next.js(v.10.0.4) and NextAuth(v.3.23.3) for a project which requires social authentication. I'm able to login/logout via a custom login page including a session-based social authentication system provided by NextAuth.
Now I would like to store the user's information in an external API and later on, I'd like to fetch the user's data via JWT.
I'm not sure how should I approach this. Any suggestion/example/solution idea will be highly appreciated. Thanks :)
api/[...nextauth].js]
import NextAuth from 'next-auth'
import Providers from 'next-auth/providers'
import axios from 'axiosConfig'
const options = {
providers: [
Providers.Facebook({
clientId: process.env.FACEBOOK_ID,
clientSecret: process.env.FACEBOOK_SECRET,
}),
Providers.Google({
clientId: process.env.GOOGLE_ID,
clientSecret: process.env.GOOGLE_SECRET,
}),
],
pages: {
signIn: '/',
signOut: '/',
error: '/auth/error', // Error code passed in query string as ?error=
verifyRequest: '/auth/verify-request', // (used for check email message)
newUser: null, // If set, new users will be directed here on first sign in
},
session: {
jwt: true,
},
callbacks: {
session: async (session, user) => {
session.jwt = user.jwt
session.id = user.id
return Promise.resolve(session)
},
jwt: async (token, user, account) => {
const isSignIn = user ? true : false
if (isSignIn) {
//
}
return Promise.resolve(token)
},
},
}
export default (req, res) => NextAuth(req, res, options)

Using Microsoft Authentication Library MSAL with PnPjs

I've been reading the PnPjs page and I need to understand what it does:
https://pnp.github.io/pnpjs/authentication/msaljsclient/#calling-sharepoint-via-msal
It seems like:
import { MsalClientSetup } from "#pnp/msaljsclient";
import { sp } from "#pnp/sp/presets/all";
sp.setup({
sp: {
fetchClientFactory: MsalClientSetup({
auth: {
authority: "https://login.microsoftonline.com/mytentant.onmicrosoft.com/",
clientId: "00000000-0000-0000-0000-000000000000",
redirectUri: "https://mytentant.sharepoint.com/sites/dev/SitePages/test.aspx",
},
}, ["https://mytentant.sharepoint.com/.default"]),
},
});
const r = await sp.web();
Is providing a wrapper for a SharePoint app to be given perhaps an impersonation step, or for the app creator to allow other users to have elevated permissions? If not (oh I wish) then what does it do?
you have to add baseUrl in the setup.
import { MsalClientSetup } from "#pnp/msaljsclient";
import { sp } from "#pnp/sp/presets/all";
sp.setup({
sp: {
baseUrl: "https://{my tenant}.sharepoint.com/sites/dev/",
fetchClientFactory: MsalClientSetup({
auth: {
authority: "https://login.microsoftonline.com/mytentant.onmicrosoft.com/",
clientId: "00000000-0000-0000-0000-000000000000",
redirectUri: "https://mytentant.sharepoint.com/sites/dev/SitePages/test.aspx",
},
}, ["https://mytentant.sharepoint.com/.default"]),
},
});
const r = await sp.web();
After adding baseUrl we can get SharePoint data and it's working with above code.

#msal-browser loginPopup() method only gets the bearer token

I've a React App and I am using "#azure/msal-browser": "^2.13.1" NPM package to authenticate end users using Azure AD. I've registered my app and got my client id and tenant id etc which I use to populate MSAL config details but when I call the loginPopup() method of MSAL object instance, I can briefly see the popup login window and it closes by itself. I can see a successful response as a bearer token from this call. Though this is not what I want. I would like the web app user to enter their own credentials in the popup window and use it to authenticate against the AD of my org. Code is as per below ..
import * as msal from "#azure/msal-browser";
import {LogLevel} from "#azure/msal-browser";
const AuthService = async () => {
const MSAL_CONFIG = {
auth: {
clientId: '<appclientid>',
authority: 'https://login.microsoftonline.com/<tenantid>',
redirectUri: window.location.href,
postLogoutRedirectUri: window.location.href
},
cache: {
cacheLocation: "sessionStorage",
storeAuthStateInCookie: false,
},
system: {
loggerOptions: {
loggerCallback: (level, message, containsPii) => {
if (containsPii) {
return;
}
switch (level) {
case LogLevel.Error:
console.error(message);
return;
case LogLevel.Info:
console.info(message);
return;
case LogLevel.Verbose:
console.debug(message);
return;
case LogLevel.Warning:
console.warn(message);
return;
default:
console.info(message);
}
},
},
},
};
const scopes = {scopes: ["User.ReadWrite"]}
const msalInstance = new msal.PublicClientApplication(MSAL_CONFIG);
try {
const loginResponse = await msalInstance.loginPopup(scopes);
console.log('+++ Login response : ', loginResponse)
} catch (err) {
console.log('+++ Login error : ', err)
}
}
export default AuthService;
ok, just in case anyone else having this issue, just figured out that I needed to pass in a second value prompt: "select_account"} as a part of the scope.. see below...
const scopes = {scopes: ["User.ReadWrite"],
prompt: "select_account"}
Now it opens the popup window for the user to either select an existing logged in account or user can opt for a different one by clicking 'Select a different user' option.

Msal 2.0 - how to generate Sign Up link with Azure B2C?

In my angular app I use Azure AD B2C for authentication and MSAL.js 2.0 library to handle it. I have a "Log In" button on the home page, that is easy. But I also need a "Sign Up" button, so user would be redirected straight to Azure B2C 'Sign Up' page. Is this possible?
It is possible to redirect straight to Azure AD B2C signup page by creating individual sign-in and sign up policies and make the below changes. It won't be possible with single sign-in signup policy.
In the app config.ts add the below changes
export const b2cPolicies = {
names: {
SignIn: "b2c_1_SignIn",
signup: "B2C_1_signup",
resetPassword: "b2c_1_reset",
},
authorities: {
SignIn: {
authority: "https://fabrikamb2c.com/fabrikamb2c.onmicrosoft.com/B2C_1_SignIn"
},
signup: {
authority: "https://fabrikamb2c.b2clogin.com/fabrikamb2c.onmicrosoft.com/B2C_1_signuptest"
},
resetPassword: {
authority: "https://fabrikamb2c.b2clogin.com/fabrikamb2c.onmicrosoft.com/b2c_1_reset"
}
}
}
Create a signup button and add signup click function
signup() {
this.authService.loginPopup(b2cPolicies.authorities.signup)
}
We can use single sign-in signup policy and single signin or signup policy.
This method is for display signup signin policy:
export const msalConfig = {
auth: {
clientId: "your app client id",
authority:
"https://XXX.b2clogin.com/XXX.onmicrosoft.com/<b2c policy name>",
redirectUri: AZURE_REDIRECT_URI,
postLogoutRedirectUri: "/",
knownAuthorities: [
"https://XXX.b2clogin.com/XXX.onmicrosoft.com/<b2c policy name>",
redirectUri: AZURE_REDIRECT_URI",
],
},
cache: {
cacheLocation: "localStorage",
storeAuthStateInCookie: true,
},
};
export const loginRequest = {
scopes: ["https://XXX.onmicrosoft.com/api/XXX"],
};
//Click on login
const handleLogin = () => {
instance.loginPopup(loginRequest);
};
This method is for display individual signup policy:
const handleSignup = () => {
instance.loginPopup({
authority:
"https://XXX.b2clogin.com/tfp/XXX.onmicrosoft.com/<b2c policy name>",
clientId: "your app client id",
redirectUri: AZURE_REDIRECT_URI,
postLogoutRedirectUri: "/",
knownAuthorities: [
"XXX.b2clogin.com/rentpundit1.onmicrosoft.com/<b2c policy name>",
],
protocolMode: "OIDC",
});

Resources