I’m trying to upgrade to a passwordless non-lock authentication and I have all of it working from the Auth0 side, but when trying to use: auth0.getDelegationToken() to delegate the firebase token, that is not available in v8 and looking at the docs, there is no way to delegate tokens in v8. So how do I continue to use Auth0 and Firebase together?
As you observed the documentation indicates that delegation is not supported in Auth0.js v8. Although whenever possible it’s recommended to upgrade to the latest version if you intend to use delegation for that particular use case the alternatives are either to continue to use v7 for that call or to call the delegation endpoint directly.
The reason for the lack of support in Auth0.js v8 is that most of what the delegation endpoint offered has been superseded by other endpoints/functionality. The current exception is the use case you refer to, but for that you can still make use of v7 which has mentioned in the GitHub repository is still being supported alongside v8.
I can’t call the delegation endpoint because I am a new tenant and the grant-type (urn:ietf:params:oauth:grant-type:jwt-bearer) is not available for me. What can I do so that I can authenticate Firebase API using Auth0 ? Here is how it is described in the documentation: Auth0
I can’t call the delegation endpoint because I am a new tenant and the grant-type (urn:ietf:params:oauth:grant-type:jwt-bearer) is not available for me. What can I do so that I can authenticate Firebase API using Auth0 ? Here is how it is described in the documentation: https://auth0.com/authenticate/vanillajs/firebase
Thanks for posting this in a separate question with more details; I provided a reply through that question: http://community.auth0.com/answers/6310/view
So what do we do then? Can anyone at Auth0 provide a single example of how to use Auth0 SDK8 with Firebase? I built the demo of my app with SDK7 using “legacy” delegation, then I went to create a new account for the real app, and sure enough legacy delegation is not available to me so I’m stuck. Why did you guys disable delegation without providing examples of how to do Firebase Auth with SDK8?
Using @nikko blog post: Firebase and Auth0 v8 from legacy v7 delegation | by Nikko Ambroselli | Medium
for inspiration I came up with this example using a Firebase cloud function to delegate the Auth0 token since that has been removed on Auth0 side. To create a custom token in Firebase function, you need to generate a service account JSON file. In your firebase console, go to Project Settings > Service Accounts and then click “Generate New Private Key”. Save that generated json file in your functions directory as service-account.json and deploy. You also need to create a new Non-Interactive client in your Auth0 account and use that client’s ID on the back-end.
Here’s what the firebase functions index.js looks like:
const admin = require('firebase-admin');
const cors = require('cors')({origin: true});
const auth0 = require('auth0-js');
var auth0Web = new auth0.WebAuth({
domain: 'YOURAUTH0DOMAIN',
clientID: 'YOURCLIENTID'
});
var serviceAccount = require("./service-account.json");
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
databaseURL: "https://YOURPROJECTID.firebaseio.com"
});
exports.delegateToken = functions.https.onRequest((req, res) => {
cors(req, res, () => {
let userId = req.body.userId;
const accessToken = req.headers.authorization.split('Bearer ')[1];
auth0Web.client.userInfo(accessToken, function(err, user) {
if (err) {
console.log(err)
res.status(403).send('Unauthorized');
} else {
if (userId == user.user_id) {
admin.auth().createCustomToken(userId)
.then(function (customToken) {
res.send(customToken)
})
.catch(function (error) {
console.log('Error creating custom token:', error)
})
} else {
res.status(403).send('Unauthorized');
}
}
});
});
});
And on your front end, just like you parseHash normally after a login, I do an ajax call to the firebase function with the Auth0 user ID which returns the custom token that we now use to sign in:
export const app = Firebase.initializeApp(fbconfig)
var result = auth0.parseHash(window.location.hash)
if (result && result.accessToken) {
var id_token = result.idToken;
window.location.hash = ''
auth0.getUserInfo(result.accessToken, function (err, profile) {
if (err) {console.log(err) }
// Get CustomFirebase Token
axios({
method: 'post',
data: {
userId: profile.user_id
},
baseURL: functionsURL,
url: '/delegateToken',
headers: {
Authorization: 'Bearer ' + result.accessToken
}
})
.then(response => {
app.auth().signInWithCustomToken(response.data).catch(function(error) {
console.log(error)
});
})
}
}
Have limited testing on this, and don’t feel 100% comfortable storing the service-account.json file on the server, but this appears to be a solution that maybe others can take and improve - please let me know if you do. Not sure why something like this didn’t come from Auth0 directly, it appears they have moved on from supporting Firebase users.
You should validate the request is coming from a valid client. With the code you provided anyone can post the the cloud function and create a session. You want to only limit this to specific users.
- in first example: attach the result.accessToken to the headers of your /delegateToken call
- in second example before generating firebase token, validate the request from the client is valid using the ‘Authorization’ header (step 1). Use auth0 node js library and non interactive client credentials to validate token
Without these changes anyone could gain access your firebase API
you’ll also want to add these rules to your firebase to prevent users from seeing all data. (change the rule depending on your use case) firebase rules · GitHub
@nikko I updated the code above, would be greatly appreciated if you could check that the additions make this properly secure.
much better! Well done
For info on why you have to store the Firebase service-account.json in your functions directory and load the admin with that when needing createCustomToken:
So what do we do then? Can anyone at Auth0 provide a single example of how to use Auth0 SDK8 with Firebase? I built the demo of my app with SDK7 using “legacy” delegation, then I went to create a new account for the real app, and sure enough legacy delegation is not available to me so I’m stuck. Why did you guys disable delegation without providing examples of how to do Firebase Auth with SDK8?
adam your solution works for me - thank you for taking the time to post it here.
The only down side is that it necessitates paying $25 to google for each of my firebase environment projects because the free tier of firebase disallows external network requests in firebase functions. For dev, staging and production this is $900 a year; not something I can afford for more than a few months as a work around for Auth0 deprecated functionality for a new customer like me; it makes more sense for me to transition to Firebase authentication and bypass the problem completely – I love Auth0 but they are kind of forcing my hand here.
@jmangelo with the changes that are currently in store with Auth0.js beta 5 (GitHub - auth0/auth0.js: Auth0 headless browser sdk) do not look promising – I don’t see a re-addition of getDelegationToken. Is there a new flow or documents in process to solve this issue in Auth0 v 9? A roadmap for its release?
At this time there’s no concrete information available to be shared, but it’s highly likely that what’s made available has no connections to existing delegation even in naming.
@thefastcat You are correct that you have to be on a paid plan to use external API calls on Firebase, technically. In my testing, I have had it still work on the free plan at a very limited rate (and with warnings in the console) - this may work for you on your dev environment.
@thefastcat
Also, you should look at the Blaze plan, which is “pay as you go” - that’s what I use for my plans and my dev environment is typically $1.00/month since it’s only me causing bandwidth (and I don’t use large files). Depending on your production traffic and types of stored files, the blaze plan might be within your budget(I think unless you get a LOT of traffic will be less than $25/mo), not only do you get the external API calls, but you also get daily DB backups, which I think you should have for a production site anyway.