Social sign-in helpers for Dash (frontend assets + verification)
Project description
Dash Social Signin
Social sign-in helpers for Dash. This package ships vanilla JS/CSS assets that render OAuth provider buttons and redirect the user to the provider authorization endpoint, plus server-side helpers to verify the OAuth callback.
Note: OAuth requires a backend to exchange the authorization
codefor tokens. In Dash, the backend is your Dash server (Flask).
Install
pip install dash-social-signin
Quick start
- Copy assets into your Dash app's
assets/folder:
from dash_social_signin import install_assets
# Point this to your Dash app's assets directory
install_assets("./assets")
- Add a container with configuration:
from dash import Dash, html
from dash_social_signin import build_container
app = Dash(__name__)
app.layout = html.Div(
build_container(
{
"providers": {
"google": {
"clientId": "YOUR_GOOGLE_CLIENT_ID",
"redirectUri": "https://your.app/auth/callback",
"scope": "openid email profile",
"state": "abc123"
},
"github": {
"clientId": "YOUR_GITHUB_CLIENT_ID",
"redirectUri": "https://your.app/auth/callback",
"scope": "read:user user:email"
}
}
},
id="social-signin"
)
)
if __name__ == "__main__":
app.run_server(debug=True)
The JS will render buttons into the container automatically.
Example app
See examples/app.py for a runnable demo.
The example includes placeholders for all supported providers.
Set provider credentials as environment variables before running the example:
export GOOGLE_CLIENT_ID="your-google-client-id"
export GOOGLE_CLIENT_SECRET="your-google-client-secret"
You can also use a .env file. Use .env.example as a guide.
To load .env automatically in the example app:
pip install python-dotenv
Use the same pattern for other providers, e.g. GITHUB_CLIENT_ID / GITHUB_CLIENT_SECRET.
If you use the PKCE start route, set DASH_SOCIAL_SIGNIN_SECRET to enable Flask sessions. See .env.example for the full list.
Set BASE_URL to match your deployment origin. Defaults to http://localhost:8050 if not set:
# local dev
BASE_URL=http://localhost:8050
# tunnel or production
BASE_URL=https://your-tunnel-or-domain.com
python examples/app.py
Minimal backend callback example (Flask, Google)
This is the smallest possible server-side route that receives the authorization code and exchanges it for tokens with Google.
It includes optional PKCE support (recommended) and a simple userinfo fetch.
import base64
import hashlib
import os
import secrets
import requests
from flask import request, redirect, session
def build_pkce_verifier() -> str:
return secrets.token_urlsafe(64)
def build_pkce_challenge(verifier: str) -> str:
digest = hashlib.sha256(verifier.encode("utf-8")).digest()
return base64.urlsafe_b64encode(digest).rstrip(b"=").decode("utf-8")
@app.server.route("/auth/callback")
def auth_callback():
code = request.args.get("code")
if not code:
return "Missing code", 400
token_url = "https://oauth2.googleapis.com/token"
data = {
"grant_type": "authorization_code",
"code": code,
"redirect_uri": "https://your.app/auth/callback",
"client_id": os.environ.get("GOOGLE_CLIENT_ID"),
"client_secret": os.environ.get("GOOGLE_CLIENT_SECRET"),
}
# Optional PKCE: store the verifier in session before the auth redirect
# and send it here. If you did not use PKCE, remove this field.
code_verifier = session.get("pkce_verifier")
if code_verifier:
data["code_verifier"] = code_verifier
resp = requests.post(token_url, data=data, timeout=10)
resp.raise_for_status()
tokens = resp.json()
userinfo = requests.get(
"https://openidconnect.googleapis.com/v1/userinfo",
headers={"Authorization": f"Bearer {tokens.get('access_token')}"},
timeout=10,
).json()
# TODO: create a session / set cookies, then redirect into the app
return redirect("/")
Verification helpers (Dash server)
These helpers run on the same Dash server process to exchange the code for tokens and fetch a user profile when supported.
Store provider credentials in environment variables (or your secrets manager) and pass them into the helper.
from flask import request
from dash_social_signin import verify_oauth_callback
@app.server.route("/auth/callback")
def auth_callback():
provider = request.args.get("provider")
code = request.args.get("code")
if not provider or not code:
return "Missing provider or code", 400
tokens, userinfo = verify_oauth_callback(
provider=provider,
code=code,
redirect_uri=f"https://your.app/auth/callback?provider={provider}",
client_id="YOUR_CLIENT_ID",
client_secret="YOUR_CLIENT_SECRET",
)
# TODO: create a session / set cookies, then redirect into the app
return "Signed in"
PKCE start route (Dash server)
Use a small server route to generate a PKCE verifier and redirect to the provider. Then point authUrl to this route.
from flask import redirect, request, session
from dash_social_signin import build_authorize_url, build_pkce_challenge, build_pkce_verifier
@app.server.route("/auth/start")
def auth_start():
provider = request.args.get("provider")
if not provider:
return "Missing provider", 400
verifier = build_pkce_verifier()
session[f"pkce_verifier:{provider}"] = verifier
challenge = build_pkce_challenge(verifier)
auth_url = build_authorize_url(
provider=provider,
client_id="YOUR_CLIENT_ID",
redirect_uri=f"https://your.app/auth/callback?provider={provider}",
scope=request.args.get("scope"),
state=request.args.get("state"),
response_type=request.args.get("response_type", "code"),
code_challenge=challenge,
)
return redirect(auth_url)
Supported providers
- GitHub
- X (Twitter)
- Microsoft
- Apple
- Discord
- Slack
Note: Some providers do not return userinfo. Apple returns None for userinfo.
Connect and contribute
- PayPal: https://www.paypal.com/paypalme/omonbudeemma
- LinkedIn: https://www.linkedin.com/in/budescode
Provider config
Each provider accepts:
clientId(required)redirectUri(required)scope(optional, provider specific)state(optional)responseType(optional, defaultcode)extraParams(optional dict of additional query params)userinfoParams(optional dict of params to send to your backend start route)authUrl(optional override)
When using a backend start route (like /auth/start), userinfoParams is serialized to
the userinfo_params query param. The example app reads this value, stores it in the
session, and passes it into verify_oauth_callback as extra_userinfo_params.
Backend exchange
After the redirect, your Dash server should handle the code query param and exchange it for tokens using the provider's OAuth token endpoint.
License
MIT
Provider credential setup (step-by-step)
Use these steps to create credentials for each provider. The redirect URL must match exactly. For local dev, the pattern is:
- Redirect URI: http://localhost:8050/auth/callback?provider=PROVIDER
- JavaScript origin (if required by the provider): http://localhost:8050
If you are using a tunnel, replace http://localhost:8050 with your tunnel origin and
update the redirectUri in examples/app.py to match exactly.
Env vars:
export GOOGLE_CLIENT_ID="your-google-client-id"
export GOOGLE_CLIENT_SECRET="your-google-client-secret"
Alternatively, add these to .env (the example app loads examples/.env automatically).
Steps:
- Open Google Cloud Console and select (or create) a project.
- Go to OAuth consent screen, set the app name and required fields, and save.
- Go to Credentials -> Create credentials -> OAuth client ID, or open https://console.cloud.google.com/auth/clients/create
- Choose Application type: Web application.
- Add Authorized JavaScript origins:
- Add Authorized redirect URIs:
- Save and copy the Client ID and Client Secret.
Env vars:
export FACEBOOK_CLIENT_ID="your-facebook-app-id"
export FACEBOOK_CLIENT_SECRET="your-facebook-app-secret"
Steps:
- Open Meta for Developers and create an app.
- During app creation, select the "Authenticate and request data from users with Facebook Login" use case.
- Add the Facebook Login product (if it is not already added).
- In Facebook Login settings, add Valid OAuth Redirect URIs:
- In App settings -> Basic, copy App ID and App Secret.
GitHub
Env vars:
export GITHUB_CLIENT_ID="your-github-client-id"
export GITHUB_CLIENT_SECRET="your-github-client-secret"
Steps:
- Go to GitHub Settings -> Developer settings -> OAuth Apps.
- Click New OAuth App.
- Set Authorization callback URL:
- Save and copy Client ID and Client Secret.
X (Twitter)
Env vars:
export X_CLIENT_ID="your-x-client-id"
export X_CLIENT_SECRET="your-x-client-secret"
Steps:
- Open the X Developer Portal and create a project/app.
- Enable OAuth 2.0 (PKCE recommended).
- Add Callback URL:
- Save and copy Client ID and Client Secret.
Notes:
- X OAuth2 Authorization Code flow requires PKCE. Use the
/auth/startroute and ensure the storedcode_verifieris sent on the token exchange. - X requires HTTP Basic Auth (client ID and secret as
Authorization: Basic ...) on the token endpoint — the library handles this automatically. - If you see "Something went wrong" on the consent screen, ensure a
stateparameter is included in the authorization request. X requires it — the/auth/startroute generates one automatically if you don't supply one.
PKCE wiring (example):
@app.server.route("/auth/start")
def auth_start():
provider = request.args.get("provider", "x")
verifier = build_pkce_verifier()
session[f"pkce_verifier:{provider}"] = verifier
challenge = build_pkce_challenge(verifier)
auth_url = build_authorize_url(
provider=provider,
client_id="YOUR_X_CLIENT_ID",
redirect_uri=f"https://your.app/auth/callback?provider={provider}",
scope="tweet.read users.read",
code_challenge=challenge,
)
return redirect(auth_url)
@app.server.route("/auth/callback")
def auth_callback():
provider = request.args.get("provider", "x")
code = request.args.get("code")
verifier = session.pop(f"pkce_verifier:{provider}", None)
return verify_oauth_callback(
provider=provider,
code=code,
redirect_uri=f"https://your.app/auth/callback?provider={provider}",
client_id="YOUR_X_CLIENT_ID",
client_secret="YOUR_X_CLIENT_SECRET",
code_verifier=verifier,
)
Env vars:
export LINKEDIN_CLIENT_ID="your-linkedin-client-id"
export LINKEDIN_CLIENT_SECRET="your-linkedin-client-secret"
Steps:
- Go to LinkedIn Developers and create an app.
- In Auth settings, add Authorized redirect URLs:
- Copy Client ID and Client Secret.
Notes:
- LinkedIn uses
client_idandclient_secretin the POST body for token exchange — not HTTP Basic Auth. - PKCE is not enabled by default for LinkedIn apps. It is only available for native clients and requires
explicit activation by contacting LinkedIn. For web apps with a
client_secret, PKCE is not needed. The library disables PKCE for LinkedIn automatically. - Per LinkedIn's docs: "Once you have the app created, please reach out to your point of contact at LinkedIn, and we will enable PKCE OAuth 2 flow for your app."
Microsoft
Env vars:
export MICROSOFT_CLIENT_ID="your-microsoft-client-id"
export MICROSOFT_CLIENT_SECRET="your-microsoft-client-secret"
Steps:
- Go to Azure Portal -> App registrations -> New registration.
- Add a Web platform and set Redirect URI:
- Save and copy Application (client) ID.
- Create a client secret under Certificates & secrets.
Apple
Env vars:
export APPLE_CLIENT_ID="your-apple-service-id"
export APPLE_CLIENT_SECRET="your-apple-client-secret"
Steps:
- Go to Apple Developer -> Certificates, Identifiers & Profiles.
- Create an App ID (type: App) and enable the Sign In with Apple capability.
- Create a Services ID and link it to the App ID above. The Services ID identifier
(e.g.
com.yourname.appname) becomes yourAPPLE_CLIENT_ID. - In the Services ID, enable Sign In with Apple and configure:
- Domain:
your-tunnel-or-domain.com(nohttps://) - Return URL:
https://your-tunnel-or-domain.com/auth/callback?provider=apple
- Domain:
- Go to Keys, create a key with Sign In with Apple enabled, and download the
.p8file. Note the Key ID and your Team ID (shown top-right in the portal). - Generate
APPLE_CLIENT_SECRETas a JWT using the.p8key — it expires after 6 months max:
import jwt, time
team_id = "YOUR_TEAM_ID"
client_id = "YOUR_SERVICES_ID" # same as APPLE_CLIENT_ID
key_id = "YOUR_KEY_ID"
private_key = open("AuthKey_XXXXXXXXXX.p8").read()
payload = {
"iss": team_id,
"iat": int(time.time()),
"exp": int(time.time()) + 86400 * 180, # max 6 months
"aud": "https://appleid.apple.com",
"sub": client_id,
}
secret = jwt.encode(payload, private_key, algorithm="ES256", headers={"kid": key_id})
print(secret)
Install PyJWT and cryptography first: pip install PyJWT cryptography
The printed value is your APPLE_CLIENT_SECRET. Regenerate it before it expires.
Discord
Env vars:
export DISCORD_CLIENT_ID="your-discord-client-id"
export DISCORD_CLIENT_SECRET="your-discord-client-secret"
Steps:
- Go to Discord Developer Portal and create an application.
- In OAuth2 settings, add Redirects:
- Copy Client ID and Client Secret.
Slack
Env vars:
export SLACK_CLIENT_ID="your-slack-client-id"
export SLACK_CLIENT_SECRET="your-slack-client-secret"
Steps:
- Go to Slack API and create an app.
- In OAuth & Permissions, add Redirect URLs:
- Copy Client ID and Client Secret.
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters