Hi there. I'm trying to implement auth with multiple custom providers. I have the following code...
g
Hi there. I'm trying to implement auth with multiple custom providers. I have the following code to create a list of providers based on a configuration file
Copy code
javascript
const providers = connections.map(({ id, authUrl, tokenUrl, clientId, clientSecret, scopes }) => {
  return {
    id,
    get: (redirectURI: undefined | string, authCodeFromRequest: undefined | string) => {
      return {
        accessTokenAPI: {
          url: tokenUrl,
          params: {
            client_id: clientId,
            client_secret: clientSecret,
            grant_type: "authorization_code",
            redirect_uri: process.env.AUTH_SUCCESS_REDIRECT_URI,
            code: authCodeFromRequest || '',
          }
        },
        authorisationRedirect: {
          url: authUrl,
          params: {
            client_id: clientId,
            scope: scopes,
            response_type: "code",
            redirect_uri: process.env.AUTH_SUCCESS_REDIRECT_URI,
          }
        },
        getClientId: () => clientId,
        getProfileInfo: async (accessTokenAPIResponse: any) => {
          console.log(accessTokenAPIResponse);
          return {
              id: "...",
          };
        }
      }
    }    

  }
});
I can successfully login with a provider and I can see I can get redirected to the
process.env.AUTH_SUCCESS_REDIRECT_URI
. But the code inside
getProfileInfo
is never called. Also, I have followed the guide (https://supertokens.com/docs/thirdparty/common-customizations/getting-provider-access-token) to get the provider access token but that doesn't get called either. What am I doing wrong?
Should I be doing something special with my custom redirect uri? Should I handle the response in anyway myself?
r
this seems about right
when the provider redirects you back to your app, does the frontend call the signinup API?
if that is called, what's the input and the result of that API call? And if it's not called, what path on your website are you getting redirected back to?
g
I am not sure if it does. Should I configure the front-end to call the signup API? Or is it done automatically by the SDK?
All I do in the frontend is that I initiate the process by
ThirdParty.redirectToThirdPartyLogin({ thirdPartyId: 'slack' })
Also, please note that the
process.env.AUTH_SUCCESS_REDIRECT_URI
that I use as a redirect URI is in fact a custom API route
/auth/success
. The route handler then redirects to the frontend website.
Should the redirect URI be a path to my frontend?
I was going through older posts to see if I can find the answer and I stumbled upon this old message of yours: https://discord.com/channels/603466164219281420/990970569241554964/990984170387955842 Is this what you mean by call the signinup API?
r
Oh right. If you have made your own callback route and are not using the default sdk’s then you have to call the signinup API. There should be a function exposed by the SDK to do that
g
Thanks @rp_st ! Which of the functions should I call?
g
oh cool! I found it last night but I wasn't sure what input is! So I'll try and call it without args
is there any resource that explains the lifecycle of events and which functions should be called and when? This might be helpful in cases where you customize things and the recipe is not followed exactly?
Also, how does the SDK know the
state
value returned by the provider in the callback if I am handling it in my own route? Do I need to pass any arguments somewhere?
r
We are writing docs for custom Ui
The function reads the state from the query params of the callback. And tallies it with the state in localstorage that was added when you called the redirectToLogin function
g
Hmm I didn't know localStorage was used
So I'm a bit confused
r
Right. So when you redirect them user to the login page of the provider, supertoeks sets some content in localstorage like the state
g
Here's how I understand the flow works now: 1. I call this in my React app:
ThirdParty.redirectToThirdPartyLogin({ thirdPartyId: 'slack' })
2. The user goes through the auth process with the provider 3. The provider redirects the user back to whatever redirect uri I set 4. Now at this stage I need to call https://supertokens.com/docs/auth-react/modules/recipe_thirdparty.html#signInAndUp-1
is that right so far?
In my React app I have no routes so how will the callback be handled? Does Supertokens sets any routes behind the scenes?
In other words where should I call
signInAndUp
? Is there any callback returned by
redirectToThirdPartyLogin
?
r
U understood it correctly. You need to create the route for there callback. We have a route already that we provide which is /auth/callback/ but you are using a different route, so you need to make that route yourself.
You should call ThirdParty.signInUp in the callback route. This is a page that you create (since you are using your own path for it)
g
This is my React app config
So the autogenerated route is at the
/auth/callback/<providerId>
or
/login/callback/<providerId>
? According to the docs and my own config should be the
/login/callback/<providerId>
one right?
r
In this case its /login/callback/.
I assumed your websiteBasePath was still /auth
g
ok got it. And for the route to be autogenerated do I need to do anything? any config?
I didn't follow the guide to the letter since I am not interested in adding a UI for login in my case
r
You need to add our function to your router. Checkout. Backend quick setup docs for the recipe
Or you can create this route yourself manually, and render the react component for it yourself in there.
g
"You need to add our function to your route" --> Do you mean front-end route or backend?
Frontend route
Oh my bad. You should look at the frontend quick setup
Not backend
g
ok! So let's say I do not use my own redirct uri and I use the
/login/callback/<providerId>
as expected by supertokens
I checked the front-end guide and it doesn't mention anything about
SignInAndUpCallback
Keep in mind I have zero routes or react-router-dom in my app
r
ok. So there are three methods here: Method 1) Add our router function to your routes which will handle the callback screen by itself. Method 2) Make your own route on the frontend and in that route, render the
SignInAndUpCallback />
component which will take care of things for you and show our default spinner UI Method 3) Build your own route + your own UI and call the
ThirdParty.signInAndUp()
function yourself in a useEffect Since you are building your own UI, I would recommend doing Method 3
g
ok gotcha!
Out of curiosity for method 1 what is the router function you mentioned?
g
ok thank you
It'll really help when you publish the guide for the custom UI
r
It’s not out of date. It just uses the supertokens-web-js SDK which is slightly different that the supertokens-auth-react SDK.
For custom UI, ideally you should just use the supertokens-web-js SDK. But our docs are a little unstructured for that hence this confusion. But you have figured it out anyway.
g
well let's see 🙂 I'll try do the method 3 you suggested!
thanks for your help
r
Cool!
g
hi @rp_st I actually followed method 1 above and made some progress. However, when the callback gets back eventually it gets resolved to this url
login?rid=thirdparty&error=no_email_present
Looking at the error param I thought to check the
getProfileInfo
for the provider. My implementation just returns the id back and I can see that the return type: https://github.com/supertokens/supertokens-node/blob/5a00a138/lib/ts/recipe/thirdparty/types.ts#L32 doesn't require an email to be returned, just the id. What might be the issue here?
r
Ah no. It does require the email as well. If the provider returns no email, just return any randomly generated email with isVerified to true
Can you please open an issue about the incorrect type on the SDK? We will fix that right away
g
yeah sure
Also, the guide mentions that it's optional so you might want to change that
r
Well, actually technically it is optional, just that it shows an error to the user to use a different provider.
Since some providers like fb may not have emails for all users
I’m which case putting a fake email is a worse idea than asking the user to use a different login method if available.
g
ok!
r
Thanks
g
Also, since the access_token is available in this response is there any chance I can add it to the user metadata here? Instead of overriding the
signInUpPOST
Obviously the return type won't allow it now
r
Not really. The user has not yet been created in SuperTokens.
The user is created right after the getProfileInfo function is called
g
hmmm ok I got it
I'd love it if there was a diagram showing the flow of events and which functions are called and when! You might have it but I didn't find it.
Now it requires some guesswork to figure out what is called and when
r
Yeaaa. We don’t yet unfortunately. Working on it though. But I’d be happy to tell you on call.
g
for sure! I'll give it a go on my own and let you know! thanks!
r
Cool
5 Views