How to get a flespi token in a browser app with flespi login.
-
Your page opens the flespi login app
https://login.flespi.ioin a popup window withwindow.open. -
The user signs in there. Your page never sees the password — only the login app does.
-
After a successful sign-in the login app sends the token to your page (
window.opener) withpostMessage:FlespiLogin|token:{"token": "<token>", "region": {"rest": "https://flespi.io", "mqtt-ws": "mqtt.flespi.io:443", ...}}token— the flespi token, use it as theAuthorization: FlespiToken <token>headerregion.rest— REST API host of the user's region,region['mqtt-ws']— MQTT over WebSocket endpoint
-
Your page listens for the
messageevent, checks that it came fromhttps://login.flespi.io(always checkevent.origin!), takes the token and closes the popup.
There are two login entry points:
- flespi account —
https://login.flespi.io/#/login: the user logs in with a flespi account (email/password, Google, GitHub, etc.) and your page gets a token of that account. - realm user —
https://login.flespi.io/#/realm/<realm>, where<realm>is the realm public id: the user logs in as a user of the given realm (with username/password or with one of the identity providers configured in the realm). The token is issued according to the realm settings, so the user gets only the access the realm ACL allows.
Popups must be allowed for your page, and window.open must be called from a user action (a click),
otherwise the browser blocks the popup.
Copy into your page:
<button onclick="flespiLogin()">Login with flespi</button>
<script>
var popup = null
function flespiLogin () {
popup = window.open('https://login.flespi.io/#/login', 'flespi-login', 'width=500,height=650')
}
window.addEventListener('message', function (event) {
if (event.origin !== 'https://login.flespi.io' || typeof event.data !== 'string' ||
event.data.indexOf('FlespiLogin|token:') !== 0) {
return
}
var login = JSON.parse(event.data.replace('FlespiLogin|token:', ''))
if (popup && !popup.closed) popup.close()
var token = login.token.replace(/^FlespiToken /, '')
var rest = login.region && login.region.rest || 'https://flespi.io'
// use the token, e.g.:
fetch(rest + '/auth/info', { headers: { Authorization: 'FlespiToken ' + token } })
.then(function (r) { return r.json() })
.then(function (info) { console.log(info.result[0]) })
})
</script>The same, only the popup url points to the realm. Replace YOUR_REALM_PUBLIC_ID with the public id
of your realm:
<button onclick="realmLogin()">Login</button>
<script>
var REALM = 'YOUR_REALM_PUBLIC_ID'
var popup = null
function realmLogin () {
popup = window.open('https://login.flespi.io/#/realm/' + encodeURIComponent(REALM), 'flespi-login',
'width=500,height=650')
}
window.addEventListener('message', function (event) {
if (event.origin !== 'https://login.flespi.io' || typeof event.data !== 'string' ||
event.data.indexOf('FlespiLogin|token:') !== 0) {
return
}
var login = JSON.parse(event.data.replace('FlespiLogin|token:', ''))
if (popup && !popup.closed) popup.close()
var token = login.token.replace(/^FlespiToken /, '')
var rest = login.region && login.region.rest || 'https://flespi.io'
// the realm user token — use it the same way as any flespi token
fetch(rest + '/auth/info', { headers: { Authorization: 'FlespiToken ' + token } })
.then(function (r) { return r.json() })
.then(function (info) { console.log(info.result[0]) })
})
</script>index.html + main.js combine both ways on one page and show the received
tokens. The realm public id can be preset with the url parameter, e.g. index.html?realm=<realm public id>.
Run it locally with any static web server:
python3 -m http.server 8000and open http://localhost:8000.
framelogin.html shows the https://flespi.io/frame/index.html widget: a login
button that can be embedded into a page with an iframe. The widget opens the login popup itself and
relays the received token to the parent page with postMessage.