Cannot get control back from web view to react native app in OAuth flow - oauth-2.0

I'm trying to implement Google OAuth 2 signin using FormidableLab's react-native-app-auth library in my react native android application as shown below:
googleLoginPressed = async () => {
const config = {
serviceConfiguration: {
authorizationEndpoint: 'https://accounts.google.com/o/oauth2/v2/auth', tokenEndpoint: 'https://accounts.google.com/o/oauth2/v2/auth',
},
clientId: app_params.GOOGLE_CLIENT_ID, redirectUrl: 'https://<my_domain>/oauth/google',
scopes: ['openid', 'profile', 'email'], additionalParameters: { 'response-type': 'code' },
};
try {
const result = await authorize(config);
} catch (error) {
console.log(error);
}
}
This invokes a web view with Google's signin page and I could successfully authenticate myself. Google then correctly redirects to my oauth callback endpoint and populates the oauth code in the redirect url like it should. At this point, I expect react-native-app-auth to get the control back from the webview to application. Instead, the web view stays open at the redirect url page.
I have added necessary website association configuration under AndroidManifest.xml and the following code under MainActivity.java to check for getting the control back to application from the redirect url:
#Override
public void onNewIntent(Intent intent) { // this is not getting hit
super.onNewIntent(intent);
Uri appLinkData = intent.getData();
if (appLinkData != null) {
bar = appLinkData.getPath();
}
}
What I tried so far
I ensured my app can open Universal links. So website association must be working fine.
Also tried replicating the entire setup on iOS. Same result. The webview shows Google correctly redirecting to oauth endpoint but app fails to get control back.
How do I get control back from oauth web view to my react-native code?

If you are using Claimed HTTPS Schemes, which is the most recommended security option for mobile apps, you are likely to also need an interstitial page after login, that triggers the Universal Link.
My blog post has further info and a code sample you can run, though it uses plain Kotlin rather than React Native.

Related

Can login or register only with Firefox using Sanctum API authentication (CSRF token mismatch)

I am developing an SPA with Laravel 9, Vuejs 3 and Sanctum. I am newbie to vue and to Sanctum and I use the sanctum API authentication instead of the token authentication.
At this stage I am in dev and run the embedded laravel server for laravel app and vite server for SPA.
Everything is going smoothly when I sign in and out using the Firefox browser. But when I use Google Chrome or other browser based upon chrome (Brave, Vivaldi, chromium) I cannot sign in nor register. I get a CSRF token mismatch response.
Here are my login an register methods from vuex 's store
actions: {
async register({ commit }, form) {
console.log("in register of index");
await axiosClient.get("/sanctum/csrf-cookie");
return axiosClient.post("/api/register", form).then(({ data }) => {
console.log("data dans index");
console.log(data);
return data;
});
},
async login({ commit }, user) {
await axiosClient.get("/sanctum/csrf-cookie");
return axiosClient
.post("/api/login", user)
.then(({ data }) => {
commit("SET_USER", data);
commit("SET_AUTHENTICATED", true);
//commit("setAuth", true);
return data;
})
.catch(({ response: { data } }) => {
commit("SET_USER", {});
commit("SET_AUTHENTICATED", false);
});
},
Could somebody help me making out what is wrong or missing?
Edited after Suben's response
I read from somebody that the trouble in Chrome could come from the domain being localhost instead of http://localhost in sanctum config.
Thus I did that and could manage to login with both browser. The trouble is that even with a satisfactory answer to login and the reception of the csrf-token now in both browser the store state is not set despite the answer in the .then function being a valid user object.
Moreover, doing 3 similar requests after that strange situation, the 3 of them being under the auth:sanctum middleware, the first failed with csrf-token mismatch, the second succeeded and the third failed also with csrf-token mismatch. Looking at the requests, they have exactly the same 3 cookies including one with the csrf-token.
My guess is, that RESTful APIs are stateless. That means, they do not worry about sessions. https://restfulapi.net/statelessness/
As per the REST (REpresentational “State” Transfer) architecture, the server does not store any state about the client session on the server-side. This restriction is called Statelessness.
When you login a user with Laravel's SPA authentication, then you ARE storing client session data on the server-side.
So you have two options:
You are moving the endpoint /api/login to web.php (logout too!) OR...
You are using the API token based login.
EDIT:
I had my problems at first too with Laravel Sanctums SPA authentication and Vue. There is a video, which goes through a lot of cases, that might help you aswell for the future (Configuration of cors.php and more): https://www.youtube.com/watch?v=It2by1dL50I

Azure AD Ms Identity callback URL (error AADSTS50011)

I'm integrating Azure AD and MS-Identity on a web app with Angular.
It works on my machine, but when I deploy it, I get an issue with the callback URL.
First, to make sure the callback URL is ok, I extract it from the microsoft login popup window's URL:
Then, I url decode the content. The URL seems fine and it is available in my Azure app's redirect URL.
Then I login to Microsoft normally and I get this error (AADSTS50011):
Then I inspect the URL again (inside the query string from the urldecoded popup window's URL) and now the URL seems to have been "tampered with".
It's now something like this:
http://somedomain:80/some_page/somequerystring
instead of
https://somedomain/some_page/somequerystring
so I wonder if it's part of the problem or if it's normal behavior.
It is also mentionned "If you contact your administrator, send this info to them." I suppose I'm the "administrator" so what can I do with that "Copy info to clipboard" info to investigate the problem?
Is your application hosting on http (80) or https (443)? If your app service is terminating your TLS connection and handling that for you instead of your app, your sign-on will construct the redirect using the http request scheme. I hooked into the OnRedirectToIdentityProvider event to correct the scheme.
services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(options =>
{
Configuration.Bind("AzureAd", options);
options.Events ??= new OpenIdConnectEvents();
options.Events.OnRedirectToIdentityProvider += _fixRedirect;
});
...
private async Task _fixRedirect(RedirectContext context)
{
context.Request.Scheme = "https";
if(!context.ProtocolMessage.RedirectUri.StartsWith("https"))
context.ProtocolMessage.RedirectUri =
context.ProtocolMessage.RedirectUri.Replace("http", "https");
await Task.CompletedTask;
}

How do I deep link and navigate to a "LogInLoading" screen while the OAuth token exchange request is made?

Configuring my app to work with OAuth. Once I have the auth_code from the redirect uri, I want the user to be taken to a "log in loading" page, where a loading spinner is shown while the token exchange request is happening.
The app has been properly configured iOS side to allow deep linking, and I am being brought back to the app, just to the wrong page.
I have followed the official deep linking guide from React Navigation, as well as various Stack Overflow pages and Medium articles.
This is my App.tsx component:
const prefix = 'myapp://'
export const App = () => {
return (
<ThemeProvider theme={theme}>
<Routes uriPrefix={prefix} />
</ThemeProvider>
)
}
This is my Routes.ts:
const AuthStack = createStackNavigator({ Onboarding: OnboardingFlowScreen, SignIn: SignInScreen })
const AppTabBar = createBottomTabNavigator({ Feed: FeedScreen, Create: CreateScreen, Profile: ProfileScreen })
export const Routes = createAppContainer(
createSwitchNavigator({
AuthLoading: AuthLoadingScreen,
LogInLoading: { screen: LogInLoadingScreen, path: 'auth_success' },
App: AppTabBar,
Auth: AuthStack,
})
)
I should be brought back to the app and navigated to the LogInLoading screen. Am I misunderstanding? Shouldn't Linking.openURL('myapp://auth_success') take me to the page with path auth_success specified?
The URL can only launch your application.
To take the user to a particular screen, you need to provide navigation context based on the URL.
Whenever your app is opened through a remote URL, you get a call back in AppDelegate in method AppDelegate.application(_:open:options:) Here you can navigate to the screen you want.
Offocial Apple Documentation on URL Scheme
Refer to a question here IOS: Load a View Controller When App is Launched from Browser using url schemes?

How to integrate OAuth2.0 login in electron

I am newbie to electron and I am currently trying to implement an OAuth2.0 API which requires a callback URI. Url callback requires valid URL (https://myserver.com/sucess). so i tried this code snippet but does not work.
// Your GitHub Applications Credentials
var options = {
client_id: 'your_client_id',
client_secret: 'your_client_secret',
scopes: ["user:email", "notifications"] // Scopes limit access for OAuth tokens.
};
app.on('ready', () => {
// Build the OAuth consent page URL
var authWindow = new BrowserWindow({ width: 800, height: 600, show: false, 'node-integration': false });
var githubUrl = 'https://github.com/login/oauth/authorize?';
var authUrl = githubUrl + 'client_id=' + options.client_id + '&scope=' + options.scopes;
authWindow.loadURL(authUrl);
authWindow.show();
function handleCallback (url) {
console.log(url);
}
// Handle the response from GitHub - See Update from 4/12/2015
authWindow.webContents.on('will-navigate', function (event, url) {
handleCallback(url);
});
authWindow.webContents.on('did-get-redirect-request', function (event, oldUrl, newUrl) {
handleCallback(newUrl);
});
// Reset the authWindow on close
authWindow.on('close', function() {
authWindow = null;
}, false);
});
also, i used angular js route but does not work either.
so I'm wondering if there is a way to run server inside electron app to serve app from URL (https://localhost:3000) and if so how this will affect app behavior at packaging and distributing time, i means does the app will run from the same port
... any suggestions will help about how i can approach this problem. thank you
I had the same issue last week, i needed to integrate my electron app with vkontakte api which uses form of OAuth protocol. What you can do:
1) You launch local node http server, probably in separate process as i did.
2) You request code through oauth link and set redirect uri as http://127.0.0.1:8000/, for some reason https://localhost didn't work for me.
3) In main process you wait for message with code from server, on server implemented corresponding logic (when you receive request and code in it send through process.send back to parent message with code)
4)You request access token from main process, you shouldn't change redirect_uri. You again catch response from your server.
5) You get access_token, you kill server...
But when i did all this i read their docs till end and there was stated that standalone apps, like mine for desktop could receive token in easier way through "implicit flow", and you can get your token with only one call. Hope my experience could be extrapolated on your issue. Good luck!

You must be authenticated to make requests - GoogleAuthenticator

I am trying to upload videos using the .NET API on an Android Phone using Xamarin. I am unable to authenticate and I get the error in the subject line. Here is the code from Xamarin:
https://github.com/xamarin/google-apis/blob/master/src/Android/Google.Apis.Android/Apis/Authentication/GoogleAuthenticator.cs
I used HttpScoop and it appears there is no web traffic.
I am using the web application ID:
Client ID for web applications
Client ID:
*.apps.googleusercontent.com
Email address:
*#developer.gserviceaccount.com
Client secret:
-*
Redirect URIs: http://jmawebtechnologies.com
JavaScript origins: http://jmawebtechnologies.com
Here is how I create the Google Authenticator:
GoogleAuthenticator Auth ()
{
return new Google.Apis.Authentication.OAuth2.GoogleAuthenticator (ClientID, new Uri ("http://jmawebtechnologies.com"), Google.Apis.Youtube.v3.YoutubeService.Scopes.YoutubeUpload.ToString());
}
I found out I must call GetUI. This opens a browser window where the user logs into Google.
StartActivity(auth2.GetUI (this));
auth2.Completed += (sender, eventArgs) => {
if (eventArgs.IsAuthenticated) {
MakeAlert("Is auth", "Accepted!");
} else {
// The user cancelled
MakeAlert("Is not auth", "failure");
}
};

Resources