I was using Expo SDK 48 and my app was working fine with Google and Facebook authentication using a web browser based authentication scheme.
Working code:
type AuthResponse = AuthSession.AuthSessionResult & {
params: {
access_token?: string;
error?: string;
};
type: string;
}
...
const AuthProvider = ({ children }: any) => {
/* Google */
const signInWithGoogle = async (navigation: any) => {
try {
const SCOPE = encodeURI("email profile");
const RESPONSE_TYPE = 'token';
const authUrl = `https://accounts.google.com/o/oauth2/v2/auth?client_id=${GOOGLE_WEB_CLIENT_ID}&redirect_uri=${REDIRECT_URI}&response_type=${RESPONSE_TYPE}&scope=${SCOPE}`;
const { type, params } = await AuthSession.startAsync({ authUrl }) as AuthResponse;
console.log("type ==>> " + type);
console.log("params ==>> " + JSON.stringify(params));
if (type === 'success') {
checkGoogleUserInfo(params.access_token, navigation);
} else {
return;
}
} catch (error) {
console.log("Error retrieving token data from Google ==>> ", error);
}
}
}
After Expo has been upgraded to SDK 50 and expo-auth-session
to 5.4.0
, AuthSession.startAsync()
stopped working.
I'm trying to use the new method from docs and follow this example but I'm getting following error while trying to fetch from the url on code below:
Possible unhandled promise rejection: SyntaxError: JSON Parse error: Unexpected character: <
Not working code:
const endpoint = "https://accounts.google.com/o/oauth2/v2/auth";
const clientId: any = GOOGLE_WEB_CLIENT_ID;
const redirectUri: any = REDIRECT_URI;
const [discovery, setDiscovery] = useState({});
useEffect(() => {
async function loadDiscovery() {
// here is the issue causing promise rejection
const getDiscovery = await fetchDiscoveryAsync(endpoint).then((discovery) => setDiscovery({ discovery }));
// nothing is displayed in console
console.log("get getDiscovery >>>>>> " + JSON.stringify(getDiscovery));
}
loadDiscovery();
}, []);
const [request, response, promptAsync] = useAuthRequest({ clientId, scopes: ['email', 'profile'], redirectUri }, discovery);
useEffect(() => {
console.log(discovery);
if (!discovery) {
console.log("no discovery");
return;
}
if (response?.type === "error") {
console.log("response type error: " + (response.params.error || "something went wrong"))
return
}
if (!discovery || (response?.type !== "success")) {
console.log("no discovery and no response type");
return;
}
const code = response.params.code;
if (!code) {
console.log("no code");
return;
}
}, [response, discovery]);
Is that still possible to use web browser based authentication with Google and Facebook?
Edit:
I finally got a discovery
using https://accounts.google.com
as an endpoint and the result is the json below. But my response
is still null
.
{
"discovery": {
"discoveryDocument": {
"issuer": "https://accounts.google.com",
"authorization_endpoint":
"https://accounts.google.com/o/oauth2/v2/auth",
"device_authorization_endpoint":
"https://oauth2.googleapis.com/device/code",
"token_endpoint": "https://oauth2.googleapis.com/token",
"userinfo_endpoint":
"https://openidconnect.googleapis.com/v1/userinfo",
"revocation_endpoint": "https://oauth2.googleapis.com/revoke",
"jwks_uri": "https://www.googleapis.com/oauth2/v3/certs",
"response_types_supported": [
"code",
"token",
"id_token",
"code token",
"code id_token",
"token id_token",
"code token id_token",
"none"
],
"subject_types_supported": [
"public"
],
"id_token_signing_alg_values_supported": [
"RS256"
],
"scopes_supported": [
"openid",
"email",
"profile"
],
"token_endpoint_auth_methods_supported": [
"client_secret_post",
"client_secret_basic"
],
"claims_supported": [
"aud",
"email",
"email_verified",
"exp",
"family_name",
"given_name",
"iat",
"iss",
"locale",
"name",
"picture",
"sub"
],
"code_challenge_methods_supported": [
"plain",
"S256"
],
"grant_types_supported": [
"authorization_code",
"refresh_token",
"urn:ietf:params:oauth:grant-type:device_code",
"urn:ietf:params:oauth:grant-type:jwt-bearer"
]
},
"authorizationEndpoint":
"https://accounts.google.com/o/oauth2/v2/auth",
"tokenEndpoint": "https://oauth2.googleapis.com/token",
"revocationEndpoint": "https://oauth2.googleapis.com/revoke",
"userInfoEndpoint":
"https://openidconnect.googleapis.com/v1/userinfo"
}
}
How can I use this discovery document? I'm trying to get user email from Google after user enter his credentials as it was working before SDK changes.
After I finally find Google's discovery document link and using Uber authentication example, I can open the web browser authentication to enter Google's credentials:
const discovery = {
authorizationEndpoint: 'https://accounts.google.com/o/oauth2/v2/auth',
tokenEndpoint: 'https://oauth2.googleapis.com/token',
revocationEndpoint: 'https://oauth2.googleapis.com/revoke'
};
const AuthProvider = ({ children }: any) => {
const [request, response, promptAsync] = useAuthRequest({
clientId,
scopes: ['email', 'profile'],
redirectUri,
responseType: 'code',
},
discovery
);
useEffect(() => {
console.log("request >>>>>>>>>>>>>>>>>> " + JSON.stringify(request));
console.log("response >>>>>>>>>>>>>>>>>> " + JSON.stringify(response));
console.log("discovery >>>>>>>>>>>>>>>>>> " + JSON.stringify(discovery));
}, [response]);
...
/* Google */
const signInWithGoogle = async (navigation: any) => {
try {
promptAsync();
} catch (error) {
console.log("Error retrieving token data from Google ==>> ", error);
}
}
I'm still facing an error after enter Google account login:
Something went wrong trying to finish signing in
but I think this should be discussed on another question.