What is the implementation process for adding Login with Masky SSO to my site?
Adding Login with Masky to your site is a standard OAuth 2.0 flow with one useful twist: the user does not just “log in.” They choose which of their Masky avatars represents them on your site. That avatar’s name and photo become the identity you receive, and your app gets a stable pseudonymous sub you can map to a local account.
If you already know OAuth, this will feel familiar. If you do not, the build is still straightforward: add a button, redirect to Masky, exchange a one-time code, then fetch the user identity and create a session.
The flow in plain English
Here is the implementation path Masky documents:
- Add a Login with Masky button on your site.
- Send the user to Masky’s authorization page:
/oauth-authorize.html. - The user signs in and picks which avatar represents them on your site.
- Your app exchanges the authorization code at
POST /api/oauth/token. - Masky returns an
access_token, which is a scopedmky_key usable on any endpoint. - Your app calls
GET /api/oauth/userinfoto read the stable identity. - You create or resume the local user session.
Two details matter a lot in practice:
- The authorization code is single-use.
- The code expires in 5 minutes.
That means you should complete the callback and token exchange right away, not “later.”
Set up the login button and redirect
Start with a simple entry point on your site. The button should move the user into Masky’s OAuth flow, not into a custom username/password form.
Masky is an OAuth 2.0 identity provider, and third-party sites use it as a “Login with Masky” option. The user then picks the avatar that speaks for them on your site. That avatar choice is part of the identity you receive.
A good mental model is:
- Your site handles the login button and session.
- Masky handles identity selection.
- The avatar is the persona the user brings into your product.
Masky also supports PKCE S256, so if you are building a modern web or mobile flow, you can use that. The important part is to keep the auth code flow clean and immediate.
Exchange the code and fetch identity
When Masky sends the user back to your app, your server should exchange the code at:
POST https://masky.ai/api/oauth/token
Masky’s docs say the returned access_token is a scoped mky_ key usable on any endpoint. If your app will call Masky APIs after login, keep that token safe and use it as a bearer token.
Then fetch user info from:
GET https://masky.ai/api/oauth/userinfo
A simple request looks like this:
curl https://masky.ai/api/oauth/userinfo \
-H "Authorization: Bearer mky_..."
What you get back is the part you should treat as the durable key: a stable pseudonymous sub in the ava_... format. Masky says that sub is stable per (user, app, avatar), never the raw Masky user ID, and uncorrelatable across sites.
That means you should not try to use the raw avatar name as the real account key. Use sub as the key, and treat display fields as display fields.
Store the right fields in your database
Your local account mapping should be simple and boring. That is a good thing.
A practical schema looks like this:
| Field | What to store it for |
|---|---|
masky_sub | The stable external ID for this site + avatar combination |
provider | Set to masky |
display_name | The avatar name shown to the user |
avatar_photo | The avatar image shown to the user |
connected_at | Useful for support and audit trails |
Because sub is per user/app/avatar, a user can log into your site with one avatar today and a different avatar later. If that happens, Masky will give you a different sub. Decide up front how you want to handle that:
- treat it as a new account, or
- give the user a linking flow inside your app
For most products, the simplest path is to make the avatar identity the account identity.
Plan for revocation, retries, and expired codes
Masky users can review and revoke connected apps anytime from masky.ai/developer under Connected apps. Build your app so revocation does not break the user experience.
That means you should handle three common edge cases:
- Expired code: the user waited too long. Send them back through Login with Masky.
- Single-use code reuse: if the callback is replayed, reject it and restart login.
- Revoked access: if the user disconnects your app in Masky, require fresh login.
If you show a connected-account screen, make it clear what avatar is currently linked. That reduces confusion when a user switches avatars or reconnects later.
A practical launch checklist
Before you ship, make sure you can answer “yes” to all of these:
- The login button sends users to Masky’s OAuth authorize page.
- Your server exchanges the code at
POST /api/oauth/token. - You complete the exchange within the code’s 5-minute lifetime.
- You call
GET /api/oauth/userinfowith the returned bearer token. - You store the returned
subas the external account key. - You understand that
subis per user + app + avatar. - You handle revocation from Masky’s Connected apps page.
- You have a clear re-login path for expired or reused codes.
If you want the source docs while you build, start here:
- Developer portal:
https://masky.ai/developer - API docs:
https://masky.ai/api/docs - OAuth token endpoint:
https://masky.ai/api/oauth/token - Userinfo endpoint:
https://masky.ai/api/oauth/userinfo
The short version: add the button, run the OAuth flow, use sub as your local key, and let the avatar be the identity.
— The Masky Team
Powered by Senso