Authentication
View our React template’s authentication code for a complete example of what all these steps look like in practice together.
When a player visits your experience page on the casino (e.g. /play/dan/pachinko
), the casino loads your experience iframe url.
Your experience frontend then needs to authenticate them.
What is authentication?
This means sending a request to the hub server which will do two things:
- Reveal the user ID and username of the player on the casino
- Create a session for the player on the hub server so that the player can make authenticated requests to the hub server (e.g. to make bets)
How to authenticate
Your experience frontend authenticates the player by sending a hubAuthenticate
GraphQL request to the hub server.
mutation Authenticate {
hubAuthenticate(
input: { casinoBaseUrl: "https://moneypot.com", userToken: "..." }
) {
success {
experienceId
sessionKey
uname
userId
}
query {
hubCurrentUser {
hubBalancesByUserId {
nodes {
amount
currencyKey
hubCurrencyByCurrencyKeyAndCasinoId {
displayUnitName
displayUnitScale
}
}
}
}
}
}
}
Remember that you can add any additional GraphQL queries to the request so that you can authenticate and load any necessary initialization data in a single request.
As you can see in the query, you need to pass two things to the hub server:
userToken
: The userToken that the casino passed in the iframe urlcasinoBaseUrl
: The base URL of the page iframing your experience (i.e. strip any path and params from the url)
Since the casino passes the userToken
in the iframe url:
<iframe src="https://my-game.example.com#userToken={userToken}"></iframe>
Here’s how you can parse it:
const userToken = new URLSearchParams(window.location.hash.slice(1)).get(
"userToken"
);
And here’s how you can get the parent window URL in a cross-browser way:
Show TypeScript code
// Try getting parent window URL from different sources in order of preference
function getCasinoBaseUrl(): string | null {
const possibleUrls = [
// Check ancestor origins, not available in every browser
document.location.ancestorOrigins?.[
document.location.ancestorOrigins.length - 1
],
// Check referrer if it's different from current origin
document.referrer !== window.location.origin ? document.referrer : null,
];
const validUrl = possibleUrls.find((url) => url && URL.canParse(url));
return validUrl ? new URL(validUrl).origin : null;
}
Why not just hard-code casinoBaseUrl = "https://moneypot.com"
?
You could, but:
- It’s better practice to check who is iframing your experience
- In the future, dynamically determining the casino base URL sets the stage for supporting other MoneyPot casinos
What do I do after authentication?
Store the session key
Once you have the player’s sessionKey
, you should store it so that you can make authenticated requests to the hub server.
Just store the
sessionKey
in memory instead of in localStorage.The player will get a new session key any time they refresh the experience page which makes it less likely that the session key will expire or be hijacked by someone else using their browser.
Make authenticated requests to the hub server
You make authenticated requests by sending the session key in the Authorization
request header:
fetch("https://hub.example.com/graphql", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `session:${sessionKey}`,
},
body: JSON.stringify({
query: '...',
variables: { ... }
}),
});
Note: in practice you would use a library like graphql-request to make GraphQL requests to the hub server.
import { GraphQLClient, gql } from "graphql-request";
const client = new GraphQLClient("https://hub.example.com/graphql", {
headers: {
Authorization: `session:${sessionKey}`,
},
});
const data = await client.request(query, variables);
Our React template shows how you can set up graphql codegen and TanStack Query to work with a graphql API in a pleasant, type-safe way.
PostMessage the initial user balances
More info: PostMessage API
Once the player is authenticated (and any time the player’s balance changes), the experience is required to post the player’s balances to the casino.
parent.postMessage(
{
type: "playerBalances",
balances: {
HOUSE: 100,
BTC: 123,
},
},
"*"
);