I'm a developer at a company that has an application that is built with PHP and MySQL. We have about 300 users that have their passwords hashed with bcrypt and stored in the users table. We're looking to rebuild the application with Angular and Firebase.
My question is, how to I migrate these users over Firebase and use Firebase Auth. It's easy to migrate the profile info over, but I want to be sure that the user can still use the same email/password when they login to the new application.
Here are some approaches that I've thought of. All of these are terrible in my opinion.
A) Create a custom auth system that uses bcrypt, and then just copy the hash over. This isn't what I want because I don't want to maintain a custom auth solution.
B) Every time a user logs into the old system, grab their password from the login field, store it in plaintext, then manually create each user in Firebase with their email/password. This would require 100% of users to login before we switch to the new app. That is unlikely. Also this is obviously a breach of privacy. I'm sure it breaks some sort of law or standard. But it works and it's a last resort option.
C) Every time the user logs in to the old system, send the email/password in plaintext to a script that auto-creates a new Firebase user with the same user/email. This would require 100% of users to login before we switch to the new app. That is unlikely. It's also harder to build than option B.
None of theses options look very good. They all have downsides. Is there a better option? If not, between B and C, which is most legal/ethical? Option B tempts me because it's super simple, but I don't want to break any laws or lose the trust of my companies clients.
[From Firebase Authentication team]
Firebase has a better solution. Firebase Authentication service has the capability to batch import password hashes of your existing users, for well known hash algorithms (hmac-sha256, bcrypt, scrypt etc.). End users just sign with their existing passwords, and your app will receive a Firebase token containing the same user_id you uploaded. None of the option A/B/C is needed.
[Update 11/19] The Firebase command line tool 3.2.0 supports importing bcrypt hashed passwords to Firebase Authentication service.
Disclosure: I work at Auth0.
Disclaimer: If you really set your mind on using Firebase from a practical point of view this might not help you as it focuses on what Auth0 provides to solve problems similar to the one you described. However, from a theoretical point of view this might help you so I deemed it worthwhile to share.
Enough with the legal stuff...
Check this guide for a fully detailed view on how Auth0 supports migrating users from your custom store to a hosted one.
... automatic migration of users to Auth0 from a custom database connection. This feature adds your users to the Auth0 database one-at-a-time as each logs in and avoids asking your users to reset their passwords all at the same time.
The approach would be similar to your option C, but the only thing that would need to stay from the old system would be the database. Everyone would start using the new application and the login would happen transparently for the users. Depending on the API's made available by Firebase, you could most likely implement something similar and that would be my recommendation.
Additionally, you should not even consider any process that includes manual steps and has to deal with plain text passwords.
A final note, excellent decision on rebuilding your app to use an external authentication service, even if it's not Auth0. :)
Authentication is a hard problem and wish more application developers stopped wasting time with issues totally unrelated to the business problems that their applications solve.
The Firebase CLI very recently added an auth:import command that allows you to import an existing user database into Firebase Auth from CSV or JSON.
Related
I'm in a real build or buy struggle. GCP identity platform would serve almost all our needs.
Basically I want to build usermanagement on my own (including rbac and groups) and ONLY want to solve Login and tokens with the below requirements. I know quite a bit about jwt and authentication in general. The question I'm asking my self is just of its better to build a solution on my own or to use one existing.
Is there any alternative which supports the following:
multi tenancy (at scale >10k tenants)
MFA
social login
SSO with oidc and saml
and of course persistence (using refresh tokens)
Are there any tipps for self building? Are there any alternatives? Any direction is greatly appreciated 🙏
PS:
None of these are what I need: Ory, keycloak, okta, auth0, fusionauth, gluu
USER DATA
When you integrate OAuth there are always 2 sources of user data:
The identity data's view of users
Your own business data's view of users
I think what you are saying is that you want finer control over user data, while also externalising difficult security work.
TOKENS AND CLAIMS
The identity system should be able to include values such as Tenant ID in access tokens, regardless of which data source each value is stored in.
Similarly the User ID in your business data is also likely to be needed in tokens. This value should be provided to your APIs in a consistent way, regardless of how the user signs in, and this is managed via account linking.
DESIGNING END-TO-END FLOWS
The main thing is to think through how these will work, for both new and existing users. This detailed Curity article provides some worked examples.
CHOOSING A SOLUTION
Don't choose a third party identity system until you've designed your end to end flows and clarified your requirements. The key thing about OAuth is that it requires extensible building blocks, rather than being an out of the box solution.
Some companies start with home grown identity microservices, which can become a lot of work, but may be ok in the early days. I always recommend keeping application code portable, so that you can migrate to a better provider in future, if needed.
Are you only considering open source solutions? Azure AD ticks all of your boxes.
You should not implement security logic like authorization or authentication or encryption yourself. IMO its always better to use an existing solution - especially features like MFA are not trivial to implement.
None of these are what I need: Ory, keycloak, okta, auth0, fusionauth, gluu
Why is that? It seems to me most of those are a good option for you - especially the open source ones
I am creating a iOS native app that talks to a Flask API.
My plan is to have the iOS front-end handle log in with Auth0 lock. Afterwards, the front-end would store the JWT in local memory and use that on every API request.
On the back-end I plan to have a User table with both an internal ID field and a Auth0 ID field. Per API request I would look up the user via the Auth0 ID and then use a library like flask-bouncer to handle resource authorization.
Is this a valid approach?
Are there any out of box features of Auth0
that I am rebuilding? If so what are the advantages of using the
Auth0 version?
Are there any future implications that I am missing
with this approach?
What are the advantages of using Auth0 instead of building it myself following something like this?
Anything else to consider?
Is this a valid approach?
Depends on what you call valid. But it would work, yes.
Are there any out of box features of Auth0 that I am rebuilding? If so what are the advantages of using the Auth0 version?
You're not using authorization using scopes. See Auth0's tutorial for Flask.
Are there any future implications that I am missing with this approach?
That's a broad question that I wouldn't know an answer for.
What are the advantages of using Auth0 instead of building it myself following something like this?
You do not have to worry about signup, login, verifying emails, bruteforce protection, resetting passwords, MFA, etc. You get all of those things out of the box. But... some more complex things might require additional effort on your side.
Anything else to consider?
Make a clear decision on where you're storing what info and whether you want to store your users in your database at all. An easy pitfall is to have multiple sources of truth for certain data that's both in Auth0 and your database (e.g. first and last name). Also see the User Data Storage Best Practices.
Auth0 looks like a very promising user management solution, but I'm curious if it allows you to export a user database.
This is an important feature because:
I'd like to make my own backups. (Not so much because I'm worried Auth0 might lose my data. But what if there's a bug in my code or my Auth0 keys are compromised?)
I might want to switch user management providers someday.
From Documentation > Importing Users to Auth0, I see there's a way to import users (on-demand when you can obtain their passwords anyway). And I can see they use bcrypt for password hashing (at least by default). But I don't see any mention of exporting users.
The Auth0 Management API allows you to export your data. Additionally, we have a tool that will help you both import and export users: https://auth0.com/docs/extensions/user-import-export
For the official policy see this document: https://auth0.com/docs/policies/data-export
Auth0 does not currently provide the facility to directly export password hashes. Not on their API and not by downloading from their web interface. Probably they never will provide this doing so would somewhat reduce security since an attacker with access to your Auth0 account could then attempt to brute force all of the user's accounts rather than just the active ones.
To get a more or less compuete export of user data there are three possible ways, all of which require activity in advance.
Request a full export from support - currently you have to be already signed up for support at at least developer level for at least a month (see the document Moving out of Auth0)
Do a gradual move out by creating a new, local password hash each time the user logs in. - you will have to wait for all your users to have logged in once. This is the inverse of the procedure for migrating in to Auth0. N.B. this will mean you miss users who never log in during your migration period.
Create and store a password hash yourself using Auth0s custom database connection for use whenever your user logs in. If you already have users in Auth0 you can combine this with method 2. to migrate those users into your custom database.
The answer from Nathan Totten here covers how to get the rest of your user data, though Auth0 support should be able to provide you with an export including all of that.
I wish to create a functionality that is very similar to facebook or pokerstars if you have used them before. Basically the apps require the user to login and their information can be accessed from both browsers and native and web apps.
How can I go about achieving this? Please advice on what services to research on to accomplish this. To my current understanding. I would be creating the website in html and php and creating a webservice using RESTful protocols and hosting them on amazon aws servers. I can then connect to these servers in the native apps? I am not very clear on how the native apps will interact with the servers
If you know of any particular protocol or a better server hosting service please let me know.
If I'm interpreting your question correctly, you are looking for something like this:
The user starts either your browser app or your native app (perhaps a mobile app)
Since the user does not have an account yet, you present them with the appropriate dialog to create said account.
You then ask the "Identity Service" to create a profile for that user
The identity service returns a token for access
This is something we do in the mobile network industry all the time. Technically, we have TAC/ACS or HSS profile services, but in either case, it's the same thing -- a dedicated service and network process that:
Accepts connections from various clients (web, mobile, desktop...)
Has various primitives along the database CRUD (Create, Read, Update, Delete) model
Answers requests the database
If you want a pre-configured solution, you could just use any networked database with a RESTstyle connector for example (MongoDB maybe?) But you could also just through this in a process that talks to a NoSQL or SQLLite database. The end result is the same.
For commercial solutions, I might like at OpenStack as you can run your code on it and they have identity brokers you might be able to CoOpt.
Personally, I'd just have a datastore running on a cloud somewhere like Amazon's EC2 which answers RESTful requests such as:
Create a user with a given profile set, return a unique token
Delete a user given a token
Update elements of the profile for a given token
I'm leaving out the necessary things like security here, but you get the idea.
This also has the advantage that you can have a single identity service for all of your applications/application services. The specifics for a given application element are just sub-fields in the profile. This gives you, not only a common identity broker for web, desktop and mobile, but a single-sign-on for all your applications. The user signs in once and is authenticated for everything you have. Moving from site to site, now just became seamless.
Lastly, you place your identity management, backup, security token management, etc OUTSIDE of your application. If you later want to add Google Authenticator for second-factor authentication, you don't have to add it to every application you have.
I should also add that you don't want to keep the identity database on the direct internet connection point. Someone could make your life difficult and get ahold it later on. Rather, you want your identity server to have a private link to it. Then do something like this:
When the account is created, don't store passwords, store hashes -- much safer
Have your application (web or otherwise) compute a key as the login
In this case, the user might enter a username and password, but the application or website would convert it into a token. THAT is what you send across.
Next, using that token (and suitable security magic), use THAT as the owner key
Send that key to the datastore and retrieve any needed values
Encrypt them back into a blob with the token
Send the block
THe application decrypts the blob to get at values
Why do we do this?
First, if someone were to try to get at your identity database, there's nothing useful. It contains only opaque tokens for logins, and blobs of encrypted data. Go ahead -- take the database. We don't care.
Second, sniffing the transport gets an attacker nothing -- again, it's all encrypted blobs.
This means later on, when you have five applications using the broker, and someone hacks the network and steals the database, you don't care, because your users never gave out logins and passwords in the first place, and even if they did, the data itself is garbage to anyone without the user key.
Does this help?
I've gotten pretty spoiled by the mature frameworks available in Python (Django/Flask), so as I'm starting to learn Go, I have to wonder if there are any similar frameworks already in existence in Go to django.contrib.auth or Flask-Login?
The main use case is to handle simple user authentication and be able to extend it to accommodate some permissions-based routing within the app.
As far as I know, there are not. The closest out-of-the-box authentication you can probably get is via Google AppEngine, where the user's Google account can be retrieved and certain paths can be scoped for app administrators only.
In a standard Go web server, you will generally need to roll your own auth, but it's not as difficult as it sounds. Many frameworks isolate you from decisions which are actually quite important; in typical Go fashion, you'll need to make these decisions based on the needs of your app, and then pick the existing libraries that are right for you.
Login page
Wherever you need your users to log in, you will probably use an HTML form. These will typically be rendered using the html/template package. To retrieve the values when the form is submitted, use request.FormValue.
Database
There are a number of ways to store user information; on the filesystem with os or in a SQL database using database/sql. There are mature drivers for some NoSQL databases as well, including MongoDB and Redis.
Passwords
To compute and compare hashes to passwords, you'll want to use a preexisting mechanism so that you don't have to reinvent it yourself. For this, the go.crypto subrepository provides a bcrypt package.
Sessions
If you want to store session data, you can use a solution like gorilla/sessions. Based on your security needs, you can store the session data directly in a (optionally secured) cookie or you can store it in a backend an only store a session ID in the cookie.
From the READ.me
Allows your Martini application to support user login via an OAuth 2.0 backend.
https://github.com/martini-contrib/oauth2