how to get refresh token in Sign In with Google for Web - authentication

i was trying to migrate from old google login library to new gis library, during the process i was not able to implement refresh token logic. my app gets logout every hour the token gets expire and user have to login again. which is not good for my customer experience. please help
i tried using Javascript api code from the official website [https://developers.google.com/identity/gsi/web/reference/js-reference]
<script>
window.onload = function () {
google.accounts.id.initialize({
client_id: 'YOUR_GOOGLE_CLIENT_ID',
callback: handleCredentialResponse
});
google.accounts.id.prompt();
};
</script>

Related

react native supabase facebook login redirect callback site url

I am trying to login with facebook using Supabase on ios emulator. After logging in with Facebook, it redirects me back to localhost. I don't know exactly what to do on this side. Can you help me? I'm still very new.
const onHandleLogin = async () => {
const {data, error} = await supabase.auth.signInWithOAuth({
provider: 'facebook',
});
if (error) {
return;
}
if (data.url) {
const supported = await Linking.canOpenURL(data.url);
if (supported) {
await Linking.openURL(data.url);
}
}
};
After the login process, it still stays on the localhost address on the browser. My purpose is to send it to the application and get token information via the url, but I have no idea how.
I think I need to make changes here but I don't know what to write in the site url because it is a mobile application.
Thanks for your support and replies.
I tried to login with facebook using supabase, but after logging in, it keeps me in safari and gives token information on localhost. I want to direct the application after the login process and get the token information.
You will need to create a deep link for your React Native app: https://reactnative.dev/docs/linking and then set this as your redirect URL. Here a similar example with Flutter: https://supabase.com/docs/guides/getting-started/tutorials/with-flutter#setup-deep-links

user authentication in a react native app

I'm building a react native app in which users can login. After a user logs in, the server returns a auth token (jwt) which is stored on the device. This all works.
Now, the problem is with authenticating the user whenever something 'happens'.
After the user logs in and the token is stored, he is send to the screen 'Main'. On that screen (and all the other 'secured' screens), I want to check the auth token. I currently have the following function to do this (simplified):
// get the auth token out of the redux store
const authToken = useSelector(state => state.auth.authToken)
// the function to authenticate a user
const authenticateUser = () => {
try {
fetch('http://URL_TO_SERVER/auth/authenticate-user', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Authorization': 'Bearer ' + authToken
}
})
.then(response => response.json())
.then(responseJSON => {
if (responseJSON.response === 'OK') {
// user is authenticated
} else {
// user is NOT authenticated
}
})
}
// only run the function once
useEffect(() => {
authenticateUser()
}, [])
This works, but there is a 'lag' (because fetch returns a promise). When I open the app and go to I screen whilst I'm not logged in, the screen is shown for just a second, and after that, I'm redirected to the login screen. So it works, but I'm not sure that this is the correct way to do so.
I could add a 'layer' to each screen and show a loading modal untill the authenticateUser-function has ran, but I don't think that's the correct way to do so.
My question is: what is the best way to secure screens in a react native app? Is the way I'm doing it OK, or should I switch to another method?
Thanks in advance!
EDIT: I have checked the following articles before asking this question.
Authentication with React Native and API backend
https://scotch.io/tutorials/react-native-app-with-authentication-and-user-management-in-15-minutes
You need to come up with better logic for your auth checks. Usually there is no need to check token every time you open a new screen. Even in your example, you log in and then get sent to a Main screen only to check auth token you've just received. Likewise, should user even see "go to main screen" button when user is clearly not logged in? Do you really want to check for token every time new screen opens in the app? What happens if token is valid by the time you open the screen, but, as the time passes and user stays on the same screen, token becomes invalid?
Try this:
create a part of redux store (e.g. reducer) that will handle current authentication state. Simple "isAuthenticated" flag will do for start
you can access this flag from any screen that is connected to redux
when receiving JWT you can read it's expiration date. So, if you refreshed the token 5 minutes ago and it's not going to expire for the next 2 hours, there is no need to check if token is valid, because you can just assume that by comparing expiration date with current date any time you want
use "isAuthenticated" flag to determine whether or not to show the "go to Main screen" button, so that logged out users will not even see that button
if you need even more control, hook into navigation to check where user is trying to navigate to and allow/deny that by checking against "isAuthenticated" flag in redux store. Take a look here and here
create a service to keep track on token expiration dates and refresh tokens ahead of time if needed, or periodically check if current token is valid, and set "isAuthenticated" to false if it isn't. Create wrappers around your network functions (fetch in your example) and notify this service if status 401 is received in response to any request to the server so that the service can either refresh the token and repeat request, or let user know that he was logged out
See what i believe is the best way toachieve it is by adding a splashscreen to the app, and there you can divert logic if the token exists you can redirect to Homescreen or loginScreen.
like this :
in Splashscreen.js
componentDidMount(){
AsyncStorage.getItem('token') ? navigation.navigate('Home'):navigation.navigate('Login')
}
hope it helps.feel free for doubts

Using Cypress to Test an App That Relies on OAuth

I've inherited a Node.js web app that uses relies on OAuth. Whenever you visit a page the app ensures you've authenticated. Please note, there no Angular, React, Vue, etc here. Each page is straight up HTML.
I want to test this site using Cypress. My problem is, I'm stuck on the initial redirect from the auth provider. Cypress acknowledge OAuth is a challenge.
commands.js
Cypress.Commands.add('login', (credentials) => {
var settings = {
'clientId':'<id>',
'scope':'<scope-list>',
...
};
var body = `client_id=${settings.clientId}&scope=${settings.scope}...`;
var requestOptions = {
method: 'POST',
url: 'https://login.microsoftonline.com/...',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: body
}
cy.request(requestOptions);
});
Then, in my test, I have:
context('Home', () => {
it('Visits Successfully', () => {
cy.login();
cy.title().should('include', 'welcome');
});
});
In the test runner, I see the login POST request is occurring. I confirmed that an access token is being received using a console.log, however, my title is empty. It's like the redirect after OAuth isn't happening in Cypress. However, when I visit the site in the browser, the redirect is happening as expected.
What am I missing?
What you might be missing is confusing between the actual UI flow and the programmatic flow of doing OAuth with a 3rd party website.
What you would want to do is to complete the programmatic login and then send the required parameters to your OAuth callback URL for your app manually in the test code.
an example is given here (though it uses a different grant type it gives you an idea) https://auth0.com/blog/end-to-end-testing-with-cypress-and-auth0/#Writing-tests-using-Cypress-Login-Command
another issue on the cypress github that deals with a similar problem
https://github.com/cypress-io/cypress/issues/2085
this also might help:
https://github.com/cypress-io/cypress-example-recipes/blob/master/examples/logging-in__single-sign-on/cypress/integration/logging-in-single-sign-on-spec.js

How to authenticate users in FirefoxOS using BrowserID / Persona?

I am trying to write an FirefoxOS app for my portal which uses Mozilla Persona for authentication. How I should proceed if I want to achieve:
Allow users of my app to signup to my portal using Persona
Allow users of my app to login to my portal within the FirefoxOS app and perform some actions with the API
Depends if users is logged or not - giving access to different actions.
I have found this post with info that its integrated already: http://identity.mozilla.com/post/47114516102/persona-on-firefox-os-phones but I can't find any real examples.
What type of application I need to create? webapp or privileged?
I am trying to implement it using regular tutorial: https://developer.mozilla.org/en/Persona/Quick_Setup
But with this code:
signinLink.onclick = function() { navigator.id.request(); };
I am getting only following error:
[17:25:18.089] Error: Permission denied to access object
One thing is to make sure you're calling watch() to setup callbacks before you call request().
For example, something like this in your page:
<script src="https://login.persona.org/include.js"></script>
<script>
window.addEventListener("DOMContentLoaded", function() {
navigator.id.watch({
// Provide a hint to Persona: who do you think is logged in?
loggedInUser: null,
// Called when persona provides you an identity assertion
// after a successful request(). You *must* post the assertion
// to your server for verification. Never verify assertions
// in client code. See Step 3 in this document:
// https://developer.mozilla.org/en/Persona/Quick_Setup
onlogin: function(assertion) {
// do something with assertion ...
// Note that Persona will also call this function automatically
// if a previously-signed-in user visits your page again.
},
onlogout: function() {
// handle logout ...
},
onready: function() {
// Your signal that Persona's state- and callback-management
// business is complete. Enable signin buttons etc.
}
});
// Set up click handlers for your buttons
document.getElementById("signin").addEventListener(
'click', function() {
navigator.id.request({
// optional callback to request so you can respond to
// a user canceling the sign-in flow
oncancel: function() { /* do something */ }
});
}
});
});
</script>
Here's an example that shows this in action:
https://people.mozilla.org/~jparsons/persona_example.html
However, on FirefoxOS, you should be aware that installed apps (not packaged or certified, but generic installed apps) are given a unique origin of the form app://{uuid}, with a different uuid for each device. This is unfortunately useless for sign-in purposes because there's no way for your server to know whether an app requesting sign-in is friend or foe. The way around this problem is to run your persona code in an invisible iframe hosted on your server. Thus the iframe will have the correct origin and your server will know it's your app. The iframe and the app can communicate via postMessage.
In the case of a packaged app (sometimes called a privileged app), your origin will be the origin declared in your webapp manifest. E.g., app://yourapp.yoursite.org. This gives you better assurance that the app is really yours, but the truly paranoid may still wish to deploy the iframe trick.
Hope this helps!
j

How to automatically share some information in google plus wall

I have developed a web application with Google+ Signin. Once user click the sign in with Google+ it authorize the app and register that user. after that process, I want to automatically share some information in google plus wall from my application. For that I go through the Google plus API, "https://developers.google.com/+/" and enables api's related to login, get user information and write access. I'm trying to use Google's API to post on the currently logged in user's stream / wall / whatever. My website uses Facebook and twitter APIs to post notifications automatically on the currently logged in user's wall, but not able to post with Google's wall. I want something like Facebook and Twitter API, with Automatic Posting function and API.
Please help me to troubleshoot this problem.
For your review I am sending my sample code snippet here:
/*
<script type="text/javascript">
function googleAPIOnLoad() {
console.log("Google plus js loaded... calling client.load...");
gapi.client.load('plus','v1', function(e){
console.log("client loaded...");
console.log(e);
});
}
function signIn() {
console.log("signing in...");
gapi.auth.authorize({
client_id: "XXXXXXXXXXX",
immediate: false,
response_type: "token",
scope: ["https://www.googleapis.com/auth/plus.login https://www.googleapis.com/auth/plus.stream.write"],
requestvisibleactions: "https://schemas.google.com/AddActivity"
}, function(e) {
// callback
console.log("done!", e);
gapi.client.request({
path: "plus/v1/people/me/moments/vault",
method: "POST",
body: JSON.stringify({
type: "http://schemas.google.com/AddActivity",
target: {
type: "http://schema.org/Thing",
name: "Test Name",
description: "Test Description",
image: "http://test.test.com/Deal/Dealphoto/Thumbnail/0160475582922191382013.png"
}
})
}).execute(function(e) {
console.log("did it.", e);
});
});
}
</script>
*/
I will be very thankful to you for this.
Thanks,
Lalit
Basically you can't automatically post to a users Google+ stream. You can either use the share API with your users intentionally posting, or you can use app activities to automatically create posts that won't be visible on the users stream.
There is an open feature request you can star for a full write API method.
There is a write API in the Domains API but that only works for Google Apps users and can only post private content in that company.