I have the following code from my react native app where i've used auth0 to login users using their Facebook, Google account, Apple.
const authProviders = {
google: {
name: "google-oauth2",
icon: <GoogleIcon />,
color: cs["apple"],
},
facebook: {
name: "facebook",
icon: <FacebookIcon />,
color: cs["facebook"],
},
apple: {
name: "apple",
icon: <AppleIcon />,
color: cs["apple"],
},
};
const onSocialAuth = async (type: auth) => {
const connection = type.name;
dispatch(setProvider(connection));
const result = await LoginAs(connection);
if (result.type === "success" && Platform.OS === "ios") {
const accessToken = result.url
? result.url.match(/access_token=([^&]+)/)
: null;
const token = accessToken ? accessToken[1] : null;
const { payload } = await dispatch(
userSocialLogin({ access_token: token ?? "" })
);
if (payload?.data?.token) {
await storeAsyncData(ENUM.PREVIOUS_AUTH_PROVIDER, type.name);
dispatch(completeLogin(payload?.data?.token));
authContext.setAuth({
isUserLoggedIn: !!payload?.data?.token,
token: payload?.data?.token,
});
} else {
alert("Something went wrong while logging with " + connection);
}
} else {
// alert('Failed to log in');
}
};
return (
<View style={{ flexDirection: "column", gap: 10, alignItems: "center" }}>
{providers?.includes('google-oauth2') &&<OutlinedButton
loading={loading && provider === authProviders.google.name}
buttonStyle={{
gap: 10,
paddingVertical: verticalScale(10),
flex: 1,
}}
onPress={() => {
onSocialAuth(authProviders.google);
}}
icon={<GoogleIcon />}>
Google
</OutlinedButton>}
//other login methods
</View>
);
};
Method to handle login
export const LoginAs = async (connection: string) => {
const auth0RedirectUri =
Platform.OS === "ios"
? `${process.env.EXPO_PUBLIC_AUTH0_REDIRECT_URI}/ios/com.hello.myapp/callback`
: `${process.env.EXPO_PUBLIC_AUTH0_REDIRECT_URI}/android/com.hello.myapp/callback`;
const auth0Domain = process.env.EXPO_PUBLIC_AUTH0_AUTH_DOMAIN; //env
const clientId = process.env.EXPO_PUBLIC_AUTH0_CLIENT_ID; //production
const audience = process.env.EXPO_PUBLIC_AUTH0_AUTH_AUDIENCE;
const url =
`${auth0Domain}/authorize?` +
`response_type=token&` +
`client_id=${clientId}&` +
`redirect_uri=${encodeURIComponent(auth0RedirectUri)}&` +
`scope=openid%20profile%20email&` +
`audience=${encodeURIComponent(audience || "")}&` +
`connection=${connection}`;
const browserOptions = {
preferEphemeralSession: false,
createTask: true,
};
const result = await WebBrowser.openAuthSessionAsync(
url,
auth0RedirectUri,
browserOptions
);
return result;
};
with the above code I get the token but no refresh token.
{"error": null, "type": "success", "url": "com.hello.myapp://hello.us.auth0.com/ios/com.hello.myapp/callback#access_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImFNT05hNEdCd2xQRjFCaURwQWxJRSJ9.eyJpc3MiOiJodHRwczovL2Z1bmRpc3VhdC51cy5hdXRoMC5jb20vIiwic3ViIjoiZ29vZ2xlLW9hdXRoMnwxMDM3NTU4NjgxNjg2Nzk4NDkwNzMiLCJhdWQiOlsiaHR0cHM6Ly91YXR2Mi1hcGkuZnVuZGlzLmZpLyIsImh0dHBzOi8vZnVuZGlzdWF0LnVzLmF1dGgwLmNvbS91c2VyaW5mbyJdLCJpYXQiOjE3Mzc5NjMxMDYsImV4cCI6MTczNzk3MDMwNiwic2NvcGUiOiJvcGVuaWQgcHJvZmlsZSBlbWFpbCIsImF6cCI6IkhQSnl4eUk2ak9CZnVzYmVPZTZXY3pNRk5Cb0xra25YIn0.BqXY4zO6e6PdE_rWs4WLLf3E8pIPTlRnD2eXn4Sp1Fw5y8-nbaq6brC9YK3Be9fE2OpCszn3oRNY1q-RuWDuYP_3vcRF_rGOFbZH_oTNMms9AosnFkG_1C7GN4PFfl7pLhkWBU5Uwy_fhyU1LcI8HoBE8vsXOCSWG4KsUQhCyTBQF_hbdw52px3hdWcuyJfXYBpxIb1D9-tnk3WVZ3SyIP47aUwKGeGxqxt4FHAFLgZOxyCaGDfSXthhYZSHXYmMHnlrveQsVFz216zEkKvVjJ4NKOjEixh_3mHbhgVhPVbblzZw9LJFwjP5DaZxLHGc_oqE7yZLRRDeef7XZh3YFQ&scope=openid%20profile%20email&expires_in=7200&token_type=Bearer"}
I've also enable offline access in my Auth0 api settings.
I've also tried passing offline_access
in scope but no success on getting refresh token.
Output of console.log of response when offline_access
is added in scope:
{
"url": "com.h3llo.fundisapp://hello.us.auth0.com/android/com.hello.myapp/callback#access_token=eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6ImFNT05hNEdCd2xQRjFCaURwQWxJRSJ9.eyJpc3MiOiJodHRwczovL2Z1bmRpc3VhdC51cy5hdXRoMC5jb20vIiwic3ViIjoiZ29vZ2xlLW9hdXRoMnwxMTQzMDY4NDQ4MzIxNTkxODA3MjYiLCJhdWQiOlsiaHR0cHM6Ly91YXR2Mi1hcGkuZnVuZGlzLmZpLyIsImh0dHBzOi8vZnVuZGlzdWF0LnVzLmF1dGgwLmNvbS91c2VyaW5mbyJdLCJpYXQiOjE3MzgxMjQ5MjYsImV4cCI6MTczODEzMjEyNiwic2NvcGUiOiJvcGVuaWQgcHJvZmlsZSBlbWFpbCBvZmZsaW5lX2FjY2VzcyIsImF6cCI6IkhQSnl4eUk2ak9CZnVzYmVPZTZXY3pNRk5Cb0xra25YIn0.VHj5hKbFvwhIyMejYA0_Cab01jlMRPg2G5RVRH8lMxkNYugrUmBDqa8JKOjjGxth4waMci6pB_c456XriPKj44Eh2UqjLgcXtVlL3txwCDWNQ-2JY9z74JAnZksGX4gtuG9vKhKR-T80vhQtVnZ3i3YASSuj3h2RF9Rf3Gvm1vRg3QE1lrErZ93HQso_CgLD6lp__XwRewAN_TQJpSVI7VNPOUizpIoKHhkCIl_ki9bHl-uvF63fwXF4X1uMAZT7umqoCgly4B0_04ZBamzyLiMH6pI6qxcFh81BKupDyHuUs7mCbIYHLPQ-bxmz_gabmu_SxhRGk_RzYj_iBkMOkQ&scope=openid%20profile%20email%20offline_access&expires_in=7200&token_type=Bearer",
"type": "success"
}
I'm using machine to machine's client ID in mobile app, since i'm not using auth0 sdk for react native.
export const LoginAs = async (connection: string) => {
const auth0RedirectUri =
Platform.OS === "ios"
? `${process.env.EXPO_PUBLIC_AUTH0_REDIRECT_URI}/ios/com.hello.myapp/callback`
: `${process.env.EXPO_PUBLIC_AUTH0_REDIRECT_URI}/android/com.hello.myapp/callback`;
const auth0Domain = process.env.EXPO_PUBLIC_AUTH0_AUTH_DOMAIN; //env
const clientId = process.env.EXPO_PUBLIC_AUTH0_CLIENT_ID; //production
const audience = process.env.EXPO_PUBLIC_AUTH0_AUTH_AUDIENCE;
const state = Math.random().toString(36).substring(7);
const url =
`${auth0Domain}/authorize?` +
`response_type=code&`+
`client_id=${clientId}&` +
`redirect_uri=${encodeURIComponent(auth0RedirectUri)}&` +
`scope=${encodeURIComponent('openid profile email offline_access')}&`+
`audience=${encodeURIComponent(audience || "")}&` +
`state=${state}&` +
`connection=${connection}`;
const browserOptions = {
preferEphemeralSession: false,
createTask: true,
};
const result = await WebBrowser.openAuthSessionAsync(
url,
auth0RedirectUri,
browserOptions
);
if (result.type === 'success') {
const urlParams = new URL(result.url).searchParams;
const code = urlParams.get('code');
if (!code) {
throw new Error('No code received from Auth0');
}
// Exchange the code for tokens
const tokenResponse = await fetch(`${auth0Domain}/oauth/token`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
grant_type: 'authorization_code',
client_id: clientId,
client_secret: process.env.EXPO_PUBLIC_AUTH0_CLIENT_SECRET,
code: code,
redirect_uri: auth0RedirectUri,
}),
});
const tokens = await tokenResponse.json();
console.log("Tokens:", tokens); // Includes access_token, id_token, refresh_token
return tokens;
}
return {result: "false"};
};
I managed to get the refresh token with the above approach. I had to get code first instead of token then use the code to get the tokens