We try to set auth using our Microsoft organization provider (it’s Azure instance with Firebase authentication. There is a problem with authorization, we can get token from webview auth process.
There are a few checkopoints in handleLogin function, we after fourth checkpoint we have provider and credentials, but then when we put credentials in signInWithCredential function, we get an error Invalid credentials.
Important note: we don’t want to have authentication using login and password, auth should be completed only through a work email only.
Did anyone build Firebase authentication using Microsoft provider? Is it possible at all?
here is our AuthProvider:
import "react-native-gesture-handler";
import { createContext, useContext, useEffect, useState } from "react";
import { Alert } from "react-native";
import {
exchangeCodeAsync,
makeRedirectUri,
useAuthRequest,
useAutoDiscovery,
} from "expo-auth-session";
import * as WebBrowser from "expo-web-browser";
import { auth } from "@/firebase/config";
import {
OAuthProvider,
onAuthStateChanged,
signInWithCredential,
signOut,
User,
} from "firebase/auth";
import { UserAccountDataType } from "@/types/users";
import DataResolver from "@/Providers/DataResolver";
WebBrowser.maybeCompleteAuthSession();
type AuthProps = {
token: string | null;
// user: User | null;
// temp change for mock auth with Alex's account data
user: UserAccountDataType | null;
forceLogin: boolean;
onForceLogin: () => any;
onLogin: () => Promise<any>;
onLogout: () => Promise<void>;
initialized: boolean;
};
const provider = new OAuthProvider("microsoft.com");
provider.setCustomParameters({
prompt: "consent",
// client_id: ...,
tenant: ...,
// redirectUri: "msauth.<app name>://auth",
});
const AuthContext = createContext<Partial<AuthProps>>({});
export function useAuth() {
return useContext(AuthContext);
}
export const AuthProvider = ({ children }: any) => {
const [user, setUser] = useState<UserAccountDataType | null>(null);
const [forceLogin, setForceLogin] = useState<boolean>(false);
const [initialized, setInitialized] = useState(false);
const discovery = useAutoDiscovery(
"https://login.microsoftonline.com/<here is tenant>/v2.0"
);
const redirectUri = makeRedirectUri({
scheme: undefined,
path: "auth",
});
console.log({ redirectUri });
const clientId = '....';
const [token, setToken] = useState<string | null>(null);
// Request
const [request, , promptAsync] = useAuthRequest(
{
clientId,
scopes: ["openid", "profile", "email", "offline_access"],
// redirectUri: "msauth.com.serhantsimple://auth",
redirectUri,
},
discovery
);
useEffect(() => {
onAuthStateChanged(auth, async (u) => {
console.log({ u });
if (u) {
console.log("U", u);
setUser(u);
} else {
setUser(u);
}, []);
// https://docs.expo.dev/guides/authentication/#azure
const handleLogin = async () => {
promptAsync().then((codeResponse) => {
console.log("✅ 1. code response");
console.log({ codeResponse });
if (request && codeResponse?.type === "success" && discovery) {
console.log("✅ 2. code success");
console.log({ request, codeResponse, discovery });
exchangeCodeAsync(
{
clientId,
code: codeResponse.params.code,
extraParams: request.codeVerifier
? { code_verifier: request.codeVerifier }
: undefined,
redirectUri,
// redirectUri: "msauth.com.serhantsimple://auth",
},
discovery
)
.then(async (res) => {
console.log("✅ 3. exchange code");
console.log({ res });
const { idToken, accessToken } = res;
setToken(accessToken);
// console.log({ res });
const credential = provider.credential({
idToken,
accessToken,
});
console.log("✅ 4. credential");
console.log({ credential, provider });
signInWithCredential(auth, credential)
.then((userCredential) => {
console.log("✅ 5. sign in with credential");
console.log({ userCredential });
setUser(userCredential.user);
})
.catch((error) => {
Alert.alert("Firebase sign-in error");
console.error("Firebase sign-in error", error);
});
})
.catch((error) => {
Alert.alert("Token exchange error");
console.error("Token exchange error", error);
// console.error(error);
});
}
});
};
const handleLogout = async () => {
console.log("logout", forceLogin);
if (forceLogin) {
setForceLogin(false);
} else {
signOut(auth);
}
};
const value = {
initialized,
onLogin: handleLogin,
onLogout: handleLogout,
onForceLogin: () => setForceLogin(true),
user,
forceLogin,
token,
};
return (
<DataResolver data={value.user} loading={!value.user} error={null}>
<AuthContext.Provider value={value}>{children}</AuthContext.Provider>
</DataResolver>
);
};
```
Andrii Yarema is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.