Solana
You can easily integrate with Streambird Auth Magic Link flow with Solana wallet access. We keep track of all Streambird provisioned wallets with the associated user and securely provide access to your users client-side
.
1 - Implement Email Login/Register UI
Implement an UI for initiating login/register via Email.
2 - Configure Redirect URLs
For security reasons, we only allow you to use redirect URL preconfigured with Streambird to ensure that we send emails to your users ONLY containing redirect_urls
you whitelisted with us.
3 - Initiate Magic Link Email
Each user must be stored on Streambird Auth, so we recommend ensuring that you store our auto generated User ID from the response into your database/backend in a column or field against that user (as long as you can associate your user with the auto generated ID returned by Streambird).
We will ensure that each email is ONLY attached to a single user at any time. We will be using the LoginOrCreateUserViaMagicLink
, if a user is found with the provided email, it will be returned and magic link email sent out, otherwise, a new user will be created on the fly (aka JIT, Just in time).
In this example, we assume you are calling Streambird Auth API from your client-side via our SDK or your custom frontend Api Client. We will be using your PublicToken
, which is publishable.
curl --location --request POST 'https://api.streambird.io/v1/auth/magic_links/public/email/login_or_create' \
--header 'Authorization: PublicToken {{public_token}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"email": "sandbox@streambird.io",
"expires_in": 0,
"login_redirect_url": "http://localhost:8081/signin/authenticate",
"registration_redirect_url": "http://localhost:8081/register/authenticate",
"wallet_type": "SOL"
}'
If successful, we will return the Streambird user_id
of the user who owns the token (example response below)
{
"user_id": "user_24wFP9pDa9YiMJLun94iKykoZs2",
"app_id": "app_24ydphdixx2ydhF0E5WUFUKWNqi",
"first_name": "",
"middle_name": "",
"last_name": "",
"active": true,
"updated_at": 1627502169,
"created_at": 1627502169,
"emails": null,
"phone_numbers": null,
"wallets": null,
"email_id": "email_24oXBL3PufzHkH1Jzyjc2EXYeo7",
"phone_number_id": "",
"request_origin_token": "H1C1XGdieAhhkUzclEKl4mAFqyxhysrzE9R7sT6aFqtYzMIZGJUuBEXF9MXSGDdFKr0x7uzep2I2hVGsBbD8evri368kI6ArvXcolEOyk3Esy4YmxW381SYKzfhlNRSQ"
}
Since this is a client-side SDK authentication, we issue you a request_origin_token
that you can use to query our backend to retrieve magic link authentication status. To ensure ONLY the original device and browser session can login to the wallet address, this request_origin_token
will ONLY be shown once to you in the browser when you requested the login. An email with an associated magic_token
will be sent to your user.
With this setup, even if you user leaked the emails before the magic_token
is expired, the person will still need the original request_origin_token
only shown to the requester to access the wallet address.
4 - Verify Magic Link
In the previous step, your user will receive an email containing the magic_link
they can click on (the magic_link
has the redirect_url
you specified combined with the magic_token
. This will then redirect the user to your app with the token
in the Query parameters. A sample link is shown below,
http://localhost:8081/register/authenticate?token=supermagictoken
Your application should parse the token and send it back to your app’s backend where you can authenticate with Streambird on the validity of this token using your ApiKey
with VerifyMagicLink
endpoint.
In this example, we assume you are calling Streambird Auth API from your backend/server side. Please ensure that you NEVER expose your ApiKey
curl --location --request POST 'https://api.streambird.io/v1/auth/magic_links/verify' \
--header 'Authorization: ApiKey sk_test_KJuRUZmh1XC342h1n39gH84MuSZDyD13NfhtDkaY6IfwpQA0H' \
--header 'Content-Type: application/json' \
--data-raw '{
"magic_token": "supermagictoken"
}'
If successful, we will return the Streambird user_id
of the user who owns the token (example response below)
{
"user_id": "user_24wFP9pDa9YiMJLun94iKykoZs2",
"app_id": "app_24ydphdixx2ydhF0E5WUFUKWNqi",
"first_name": "John",
"middle_name": "",
"last_name": "Smith",
"active": true,
"updated_at": 1627502169,
"created_at": 1627502169,
"emails": null,
"phone_numbers": null,
"email_id": "email_24oXBL3PufzHkH1Jzyjc2EXYeo7",
"phone_number_id": ""
}
However, if you have not previously attached the user_id
to your users table for example, you can also use our GetIdentityUser
endpoint to retrieve the emails
and phone_numbers
attached to the user using the user_id
returned by VerifyMagicLink
endpoint.
curl --location --request GET 'https://api.streambird.io/v1/auth/users/user_24wFP9pDa9YiMJLun94iKykoZs2' \
--header 'Authorization: ApiKey sk_test_KJuRUZmh1XC342h1n39gH84MuSZDyD13NfhtDkaY6IfwpQA0H'
Sample response below:
{
"user_id": "user_24wFP9pDa9YiMJLun94iKykoZs2",
"app_id": "app_24ydphdixx2ydhF0E5WUFUKWNqi",
"first_name": "John",
"middle_name": "",
"last_name": "Smith",
"active": false,
"updated_at": 1627081626,
"created_at": 1627081626,
"emails": [
{
"id": "email_24oXBL3PufzHkH1Jzyjc2EXYeo7",
"verified": true,
"email": "johnsmith@example.com",
"updated_at": 1627081626,
"created_at": 1627081626
}
],
"phone_numbers": [
{
"id": "pn_24oXBLRv6BoHXbNZoTAZkAFlRsy",
"verified": false,
"phone_number": "+14152222222",
"updated_at": 1627081626,
"created_at": 1627081626
}
]
}
5 - Access Wallet Address
Once your user has clicked on the link in the email and your redirect_url and your server calls Streambird to verify magic_token
, the original requester/device session of this login will be able to retrieve wallet addresses via the request_origin_token
we sent back. We also recommend polling to be done in the frontend as soon as request_origin_token
is sent back to provide a loading screen for better UI/UX for the end users.
In this example, we assume you are calling Streambird Auth API from your client-side via our SDK or your custom frontend Api Client. We will be using your PublicToken
, which is publishable.
curl --location --request POST 'https://api.streambird.io/v1/auth/magic_links/public/email/login_status' \
--header 'Authorization: PublicToken {{public_token}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"request_origin_token": "H1C1XGdieAhhkUzclEKl4mAFqyxhysrzE9R7sT6aFqtYzMIZGJUuBEXF9MXSGDdFKr0x7uzep2I2hVGsBbD8evri368kI6ArvXcolEOyk3Esy4YmxW381SYKzfhlNRSQ",
"email_id": "email_24oXBL3PufzHkH1Jzyjc2EXYeo7"
}'
This request will return a success response once the user has verified the magic link. Example response shown below.
{
"user_id": "user_24wFP9pDa9YiMJLun94iKykoZs2",
"app_id": "app_24ydphdixx2ydhF0E5WUFUKWNqi",
"first_name": "",
"middle_name": "",
"last_name": "",
"active": true,
"updated_at": 1627502169,
"created_at": 1627502169,
"emails": [
{
"id": "email_24oXBL3PufzHkH1Jzyjc2EXYeo7",
"verified": true,
"email": "sandbox@streambird.io",
"updated_at": 1627503141,
"created_at": 1627502169
}
],
"phone_numbers": [],
"wallets": [
{
"id": "wallet_24oXBMIvyVJGrbqmh1pTgY6BLbM",
"app_id": "app_24ydphdixx2ydhF0E5WUFUKWNqi",
"user_id": "user_24wFP9pDa9YiMJLun94iKykoZs2",
"public_address": "GaqqqFdYtADV2cN56njn2jE5RKjVQpMXsAxUwCAEfZSF",
"wallet_type": "SOL",
"is_default": true,
"signature_exp": 1634340607,
"request_signature": "0xfb0556fdb27075ab8915bfa6b0e2e879a434ecae08c254778e1c69a9f494e2ed7d820d179e261a429d198197b751ed696e7057b3634e79fde3292caccc61eeac00",
"updated_at": 1634152344,
"created_at": 1634152344
}
]
}
Each Wallet
object contains a request_signature
(request_signature is signed by randomly generated and rotating ethereum private key that provide the holder limited time access for private key retrieval in the Vault) that can be used with PublicToken
to retrieve the private key for wallet access client-side
. Streambird NEVER access your private key directly and all data are stored on a third-party Vault to ensure security.
curl --location --request POST 'https://api.streambird.io/v1/auth/vault/public/wallets/retrieve' \
--header 'Authorization: PublicToken {{public_token}}' \
--header 'Content-Type: application/json' \
--data-raw '{
"public_address": "GaqqqFdYtADV2cN56njn2jE5RKjVQpMXsAxUwCAEfZSF",
"wallet_type": "SOL",
"signature_exp": 1634340607,
"request_signature": "0xfb0556fdb27075ab8915bfa6b0e2e879a434ecae08c254778e1c69a9f494e2ed7d820d179e261a429d198197b751ed696e7057b3634e79fde3292caccc61eeac00"
}'
Example Response:
{
"pk": "5ySwMAHswNcVPpXjCAgX3m1uBfP3o14huBT2YvTwWamaQaT9JExPHo8aUpdt8fJ4efvmL6HQ37HGu5xHCjRCavqm",
"public_address": "GaqqqFdYtADV2cN56njn2jE5RKjVQpMXsAxUwCAEfZSF",
"valid": true,
"wallet_type": "SOL"
}
Congrats! You now have access to your private key in your browser that can be sent into Web3.js or any other Solana blockchain clients to access your wallet.