How to login a user // set a user as logged-in manually in Supabase? - supabase

I'm using Supabase for auth, and I want to set a user as logged-in using my custom logic. I'm looking for something like the following:
if (logic-that-checks-if-user-performed-authentication-criteria) {
supabase.auth.setUserAsLoggedIn({email: "user#email.com"});
}
Is there some way I can do this?
Clarification:
logic-that-checks-if-user-performed-authentication-criteria would be my own custom authentication criteria, not Supabase's.
More context:
I want to add Twitter OAuth2 support as Supabase doesn't support it by default. I want to have my own API routes for handling Twitter OAuth2, and the related credentials would be stored either as user_metadata in Supabase's auth table or in my custom user table.
The user would be required to sign up with email-with-magic-link (usual Supabase code). But once they have signed up, they would have an option to connect their Twitter account (my code).
After they have connected their Twitter, they would be given an option to sign in with Twitter alongside the usual email-with-magic-link method. This part would require my original question, I would need to set the user as logged-in after I verify that the user has logged in with Twitter and the Twitter profile matches with the one I have saved in my DB.

As far as Supabase is concerned, a user is signed in if they are signed in with magic link.
It sounds like what you want to know is whether a user has gone through the Twitter OAuth flow or not. In that case, user metadata might be a good place to store that information.
Once a user goes through the Twitter OAuth flow, you could call the following code to store the fact that the user has gone through Twitter's OAuth flow.
const { data, error } = await supabase.auth.updateUser({
data: { hasLinkedTwitter: true }
})
You would be able to retrieve this information from the User object like this:
const { data, error } = await supabase.auth.getUser();
data.user?.user_metadata.hasLinkedTwitter

Related

Dynamic user role assignment after socialite signup

I want to give social signup and registration for multiple users. Multiple types (roles) of user can sign up. That means I want a different registration page for each of them. Now, if I give them to sign up via Google option, how do I identify at the controller which role to assign to the new user? Basically, how do I identify which registration page was used before to sign up via Google?
I have tried using request()->server('HTTP_REFERER') but it returns Google's URL instead of my registration page.
When the user is on your registration page (before going to the social provider's login) you can store something in the session or in the browser's localStorage.
When the return comes back from the social provider's login you can retrieve the session or localStorage data and use that.

Accessing google apis on behalf of google home user

I'm trying to develop a simple ProofOfConcept to interract with Google APIs from a Google Home using the authorization of the user through Dialogflow Fullfilment.
For example, we want to be able to create/read/update/delete contacts of users.
It's relatively easy to implement the Google SignIn but I don't know how to ask for additionnal scopes
Also, I never implemented an OAuth server before and I'm still not sure if I need too or if I could reuse en existing one.
I looked at many posts here on SO most of them was answered by #Prisoner who also provided a detailed flow in Google Home Authorization Code and Authentication with Google Account
In his answer, he mentions that we can "redirect the user to a web login page" but I still don't understand how to do that from the fullfilment
Here's the fullfilment code I used to use the Google SignIn:
//requirements
const { dialogflow, SignIn} = require('actions-on-google');
const functions = require('firebase-functions');
//initialisation
const app = dialogflow(
{
debug: true,
// REPLACE THE PLACEHOLDER WITH THE CLIENT_ID OF YOUR ACTIONS PROJECT
clientId: '1111111111111-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa.apps.googleusercontent.com'
});
//Welcome Intent
app.intent('Default Welcome Intent', (conv) => {
conv.ask(`Welcome to the demo agent, say "Connect-me" to proceed`);
});
//Default Intent
app.intent('Default Fallback Intent', (conv) => {
conv.ask(`Sorry, can you repeat please?`);
});
//Intent starting the Google SignIn
// Create an intent with the name "Start Signin"
app.intent('Start Signin', (conv) => {
//SignIn Helper (https://developers.google.com/actions/assistant/helpers#account_sign-in)
conv.ask(new SignIn(`Need to identify you`));
});
//Intent called when the user complete the authentication
// Create an intent with the name "Get Signin" and assign it the event "actions_intent_SIGN_IN"
app.intent('Get Signin', (conv, params, signin) => {
if (signin.status === 'OK') {
const payload = conv.user.profile.payload;
conv.ask(`Hello ${payload.name}. You can now access your contacts informations... but not really `);
} else {
conv.ask(`Sorry but you should authentify yourself `);
}
});
//Example of intent that I would like to make it works
app.intent('How many contacts', (conv) => {
/*
TODO: How to ask for additional scopes ("https://www.google.com/m8/feeds/" : read/write access to Contacts and Contact Groups)
NOTE: Actually, I'm more interrested on how to get the additional scopes.
I could probably do the querying contacts part by myself since it's quite documented (https://developers.google.com/contacts/v3/)
*/
conv.ask(new SignIn(`You have ${nbContacts} contacts defined in your Google Contact`));
});
exports.dialogflowFirebaseFulfillment = functions.https.onRequest(app);
You have a few related questions bundled here.
How do I ask for additional scopes with Google Sign In?
Unfortunately you can't.
This is for the user's security. Since it isn't always obvious when you're granting additional permissions via voice, and asking for too many scopes can be overwhelming with voice, they don't allow this right now.
Ok. So how do I get those additional scopes?
You referenced another post that goes through the method I propose to do that. It involves signing in and granting the scopes through a web page in the same Google Cloud Project. Under Google's cross-client identity system, these would then apply when the user connects through the Assistant as well.
So how do I direct them to a web page?
I typically either use a card with a link button for the website or a link out suggestion to the site. Both of these, however, depend on being on a visual interface that supports a web browser. So you might wish to check for this using surface capabilities.
If you are using your own OAuth server, using the combination "OAuth and Google Sign-In" method, the Assistant will take care of these sorts of things for you.
Do I need to write my own OAuth server?
No. You can use something like Auth0 to handle the OAuth part for you.

How to use Touch Id/Face Id when the back end is rest api server

I want to implement Apple's touchId/FaceId for my app.
Currently the app has Login screen, where the user enters the userId and password. I submit the userId and password to the back end server(located at let's say https://example.com/Login?username=abc&password=xyz#123(just an example)). The backend server returns me authentication cookies. This cookies I use to access the rest of the rest api services
I am reading a number of articles which tells about how you can use Apple's touch Id with https://developer.apple.com/documentation/localauthentication framework.
It displays the generic pop up asking the use the touch Id, and returns true if the touch Id authentication is successful.
My question comes up here. If I use the touch Id and the authentication is successful. How do I proceed? Basically, I would need the authentication cookies to access the rest apis.
One flow I am assuming is.
When the user enables the touchId/faceId in settings page of my app, I store the usercredentials in the keychain.
Once the user is logged out, and the user uses touch Id and authentication is successful, I access the keychain, retrieve the password for the user, call the api https://example.com/Login?username=abc&password=xyz#123 get the authentication cookies and use them for accessing the rest of the web apis.
Is my assumption correct? Or there is a better way of implementing it?
Any examples or references would be great.
Thanks.

Gettinng user profile information for OAuth2 JWT

I am making an api that accepts social logins from a few services, namely Google.
So far, the mobile app allows the user to log in to google with the OAuth2 flow, and obtains a JWT token. The first time I was able to get the profile info from the token (first name, family name, profile pic, etc...). Now, I doesn't contain all of the fields I need.
I remember reading somewhere that google will only send all the fields from time to time...
Since I'm in testing, I tend to wipe the user database often and would like to be able to count on the google JWT to re-create the account.
I'd rather use the token than hitting the userInfo API. Especially since the JWT is technically secure.
So, is there any sure way to get all of the user profile info in the id_token from the google API?
Check the 'scopes' that you define when logging in with Google. Each scope has a type of data that it returns back to the user. Be sure that you're using scope: 'profile'" when initializing the Google login. If additional scopes are necessary, use add them to the request as shown in the link below.
https://developers.google.com/identity/sign-in/web/incremental-auth
I was using an older endpoint, changed to https://accounts.google.com/o/oauth2/v2/auth and everything is ok!

Impersonate current user when calling a Google API using service account & delegation of authority

There is a marketplace requirement that if a Google Apps for Work domain admin installs our app for their domain, the admin and any users from their domain should thereafter not see a scope auth screen when accessing our app. The act of installing the app for the domain should implicitly delegate domain-wide authority for the service account associated with our app.
In order to achieve this behavior, I am trying to do delegation of authority to a service account to work on behalf of, AKA impersonate, the currently logged in user.
The code snippet below shows the various attempts that I've made to get this to work. The only one that does work is to pass a domain superuser's email address as the "sub" param (AKA prn) when creating the JWT. However, this essentially elevates a regular run of the mill domain user's privileges to those of super user which is not the desired effect.
var client = new googleapis.auth.JWT(
'<serviceaccount>#developer.gserviceaccount.com',
'localhost.pem',
null,
["https://www.googleapis.com/auth/admin.directory.user.readonly"],
// null - // 403 not auth
// {'userId' : 'domainsuperuser#email.com'} // 403 not auth
// {'userId' : 'me'} // 403 not auth
// "domainsuperuser#email.com" // works!
// "{domainsuperuser#email.com}" // not a valid email error
// 'me' // invalid impersonation prn email address
);
Does Google honor any other ID than just the email address of the person you want to impersonate such as the special 'me' value?
It feels like we are running into a chicken and egg problem here. Essentially we don't want to hardcode the email address (especially not an admin email), so it feels like we have to make an API call. But we can't make an API call without impersonating a user.
You don't need to use a service account and domain-wide delegation in this case. Instead, simply go through the normal OAuth2 flow with the user, and the approval screen will be skipped automatically.
When the admin installs the app and approves your scopes, they are essentially automatically granting you access to those scopes for all users in the domain. And while it is a requirement that users not see the approval screen, you still have to go through the OAuth2 flow with them in order get the OAuth2 token. If you launch an OAuth2 flow for the user, and don't request any scopes not already approved by the domain admin and don't set approval_prompt=force in the URL, then the OAuth2 approval screen will instantly redirect to your redirect URI, making the process invisible to the user.

Resources