Social Login
Users log in with Google or Microsoft and see your consent screen, with your name and logo. You create the OAuth client with the provider, register it in Pylo, and connect it to an app. Pylo runs the OAuth flow and hands your app a session, so your app never touches a client secret.
Logging in never creates a user. Invite or provision everyone before they try to log in.
1. Create the OAuth client
In the admin panel, go to Settings → Login Clients, click Add client, and pick the provider. Keep the dialog open: it shows the Redirect URI you register with the provider. That URI is always Pylo's own callback, never your app's URL.
- In the Google Cloud Console, set up the OAuth consent screen with your app's name and logo.
- Under APIs & Services → Credentials, create an OAuth client ID of type Web application. Add Pylo's redirect URI under Authorized redirect URIs and leave Authorized JavaScript origins empty.
- Copy the client ID and secret into the Pylo dialog.
Microsoft
- In the Azure portal, go to App registrations → New registration. Pick the supported account types that match Who can log in in the Pylo dialog: this organizational directory only for "Only accounts in my organization", or any organizational directory and personal Microsoft accounts for "Any Microsoft account".
- Add Pylo's redirect URI on the Web platform. Under Mobile and desktop applications it makes the client public, and every login fails.
- Under Certificates & secrets, create a client secret and copy its Value, not the Secret ID.
- In the Pylo dialog, enter the Application (client) ID, the Directory (tenant) ID if you picked "Only accounts in my organization", the secret, and its expiry date.
2. Connect it to your app
Go to Settings → Apps, open the app, and switch to the Login tab. For each provider, pick your client and list every Return URL your app receives logins on, one per line, exactly as your app sends it. Save.
3. Add the buttons
Next.js
@pylo/auth-nextjs ships both route handlers. The return URL is your site's origin plus
/api/auth/callback, so register https://app.example.com/api/auth/callback and, for local
development, http://localhost:3000/api/auth/callback.
1
2
3
import { createSocialStartRoute } from "@pylo/auth-nextjs";
export const GET = createSocialStartRoute();1
2
3
import { createSocialCallbackRoute } from "@pylo/auth-nextjs";
export const GET = createSocialCallbackRoute();1
2
<a href="/api/auth/google/start?redirect=/dashboard">Continue with Google</a>
<a href="/api/auth/microsoft/start?redirect=/dashboard">Continue with Microsoft</a>Use a plain <a>, not <Link>: the route redirects to the provider. After login the callback sets
the auth cookies and redirects to redirect, or /. A failed login lands on
/auth/login?error=..., so show searchParams.error there.
React
Pass your app's ID to PyloProvider as appId, for example <PyloProvider appId="your-app-id">.
Then call loginWith with a registered return URL. It redirects the page:
1
2
3
4
5
6
7
8
9
10
11
import { usePyloAuth } from "@pylo/react";
export function GoogleButton() {
const { loginWith } = usePyloAuth();
return (
<button onClick={() => loginWith("google", { returnUrl: "https://app.example.com/auth" })}>
Continue with Google
</button>
);
}On the return URL's page, completeLogin redeems the code and starts the session. It never throws:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import { useEffect } from "react";
import { usePyloAuth } from "@pylo/react";
export function AuthCallback() {
const { completeLogin } = usePyloAuth();
useEffect(() => {
completeLogin().then((result) => {
if (result.success) window.location.replace(result.redirect ?? "/");
else showLoginError(result.error?.message);
});
}, []);
return null;
}Expo
Set appId on PyloProvider as in React, install the browser and crypto modules, and register your
scheme's URL, for example myapp://auth. loginWith opens a system browser tab and resolves with
the result:
npx expo install expo-web-browser expo-crypto expo-linking1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { Button } from "react-native";
import * as Linking from "expo-linking";
import { usePyloAuth } from "@pylo/expo";
export function GoogleButton() {
const { loginWith } = usePyloAuth();
async function onPress() {
const result = await loginWith("google", { returnUrl: Linking.createURL("auth") });
if (!result.success && result.error?.code !== "CANCELLED") {
showLoginError(result.error?.message);
}
}
return <Button title="Continue with Google" onPress={onPress} />;
}With appId in pylo.config.ts, pylo generate types loginWith to the providers and return URLs
the app allows, so a typo fails type-checking. Without an SDK, redirect to /auth/<provider>/start
with app_id, return_url and a PKCE handoff_challenge, then redeem the returned code with the
redeemLoginHandoff mutation.
Troubleshooting
| You see | Check |
|---|---|
| "This login page is not set up for … login" | The return URL is registered on the app exactly as your app sends it. |
| "Login failed. Please try again." | A user with that email exists in the app. For Microsoft, the redirect URI is on Web. |
| The provider rejects the redirect URI | You registered Pylo's redirect URI from the Add client dialog, not your app's URL. |
Microsoft identifies users by their login name (UPN). To match on their email address instead, add
the optional xms_edov claim to the ID token under Token configuration.