How to store external social media account linking in the database? - node.js

Let's say we have a backend in ExpressJS. We are using simple BcryptJS to hash and store passwords and emails in the database.
Now I want to add the link social media accounts feature like this:
Now what I was wondering is what should I store in the database? Like lets say I registered using email and password, now I go in settings and add Google login, what should I store with the user's record in the database to use the Google identity in the future when needed? Like should I store the access token? the refresh token? Should I keep refreshing the token? Should I not even store the token?
Sorry if it might sound silly, but I googled around and didn't find the answer I wanted, and I have spent the last hour thinking about this. What do you guys think? And this answer might help a lost developer in the future too.

SOCIAL LOGINS
If this is your starting point, and assuming that the email used from Google or Facebook matches that used when logging in with passwords:
Field
Example Value
User ID
203
Email
john#company.com
Then when you receive the Google or Facebook response you would need to look for an email in it, either by inspecting the ID token or calling their user info endpoint. You can then match to the User ID that makes sense to your business data.
If you store anything from those providers it should be a linked record, something like this. You should only need to store access tokens from the third party provider if your app needs to access the user's Google or Facebook resources with it:
Field
Example Value
User Link ID
1039
User ID
203
Provider
Google
Subject
d2ee68ee-7853-11ec-90d6-0242ac120003
PROBLEM AREAS
The above mechanism is inherently unreliable and can easily result in duplicate users in your business data, eg if the social provider does not give you an email and the user exists already in your business data. A technique to solve this problem can be to involve the user - ask them if they exist already in your app and if so then ask them to authenticate with an existing method (password in your case) as part of onboarding to social logins.
Foreign access tokens, from Google and Facebook, are not designed to be used to secure your own APIs - you may not even be able to validate them in some cases, and you will not be able to control claims and scopes. This leads some people to write custom code to issue their own tokens.
AUTHORIZATION SERVER
For future reference, the preferred architecture is for your UIs and APIs to only talk to your own Authorization Server, which is hosted alongside APIs. This component will then manage the following aspects for you, all of which will keep the security plumbing out of your apps:
Login connections to social providers
Dealing with provider specific differences
Providing account linking capabilities
Storing linked records
Allowing you to return your own customized tokens to your own apps
In more advanced use cases the AS can also hold onto the third party access token for you via the embedded token approach.

Related

Api design with authorization from one service to another

I am creating a Shopify app which has its own Shopify oAuth. I have built an external NodeJS application to handle all the settings, handling all the dashboard analytics, etc via api's.
I need to connect these two services together. Upon installing the application on Shopify I have an endpoint on my external service to create the shop in my table. Although now on I need to allow ONLY that store to be able to view their data / update it and not modify the request to get other stores information. Also not allow the public to view these endpoints.
I was thinking of generating an Api token on the NodeJS (external) application and saving it in the Shopify Database (Another database of stores), then passing it on every request and verifying it on the external application side. I like this approach but I also feel its not as secure since someone can steal a token.
[You also don't actually "create" an account, you just Install the app, and the app makes an Api request for a new "store" entry]
I was thinking of using JWT for that but possibly can't.
Another option was combining the Api token and creating 1 admin user on the external NodeJS so that a Bearer token w/ the Api token need to be passed. This gives 1 extra layer of security since they would "need" to have this app install at least in Shopify.
What are some suggestions that I can look into?
Shopify's docs recommend a number of libraries for using their OAuth, and I would recommend using one of those until you're more familiar with the OAuth workflow. They also supply a template project that already has this wired up in an express server. Depending on where you are with your external project, you might consider starting with that and moving your existing code into it, but if not, the web/middleware section will give you an example of what to do.
To answer your specific question, I think you might be misunderstanding how OAuth works, as you would likely not generate any tokens yourself. There are a lot of lengthy explanations out there (a few here: What exactly is OAuth (Open Authorization)?), but for a really basic rundown, let's first consider a really simple traditional authentication workflow:
user registers on your site, and you store their username and a hash of the password in a table such as users
when the user tries to log in, they send a username and password. You check this against your users table, and if it matches, you generate an auth token. You then store this token along with the username in a table such as auth_tokens
for subsequent requests, they include this auth token as a header. For every single request, you look up the token in the auth_tokens table, and if it's there (and hasn't expired), you assume the request comes from the username you stored with the token and restrict access accordingly
With OAuth, you're offloading all of that to a third party. This is oversimplified a bit, but effectively works like:
user registery with third-party
when the user tries to log in to your site, you redirect them to third-party, and they log in there
third-party gives them a token and redirects them back to your site
your app calls third-party with the token, and if it's valid, third-party gives you their username (and some other info). You trust third-party, so you take their word for it that the request comes from that user and restrict access accordingly
In the case of shopify, the "other info" will include the shop, and your app can then choose to only show them info for that shop.
https://github.com/Shopify/shopify-api-node/blob/main/src/auth/session/types.ts
EDIT based on comments:
If I understand correctly, you mean that, after doing something in Shopify, you also want the same person to use your core application to update things in this external service WITHOUT Shopify in the middle, and you want to verify that it's the same person.
If so, your hesitation about the token is correct. You would essentially be handing out a password that works forever and storing it in an insecure place. There are 2 better options.
I know NOTHING about this, but it does look like Shopify has an option to be an OAuth provider for your core application as well. https://shopify.dev/api/multipass. This is essentially the same as a "Log in with Google" option. This way, you're using Shopify's tokens for everything.
Your application could have its own login, and you would need to associate your user with theirs. One easy way to do that would be using the email address. Nested in that session token you get from Shopify, you have the onlineAccessInfo:
export interface OnlineAccessInfo {
expires_in: number;
associated_user_scope: string;
associated_user: {
...
id: number;
email: string;
email_verified: boolean;
...
};
}
You would need to keep a record of this info when requests come from Shopify. If they have verified the address (the email_verified field is true), and you have verified the address, then you can assume they're the same person. You could either require that they register on your site with the same email, or you could verify it separately if they did not.

Node Server, is a database necessary for basic authentication if using oauth?

I'm learning Node, doing authentication stuff at the moment with passport.
Say my server has 2 pages, a public home page with various login options, then a super-secret page(and perhaps more) that is only accessible after authenticating.
If I'm only going to be using 3rd party strategies, is there any reason to have a database?
I know that you'd obviously need one for local user's id and pass, but if the server exclusively relies on 3rd party authentication, would session persistence be enough things to work? Or are there still various things that you would need to save for some reason (apart from logging) ?
Could you do without a database, sure... but in this case what is the point in authenticating at all? All you would be proving is that the user has a Google account which anyone can set up for free in a matter of minutes.
If your content is super secret then chances are you want to have a database of users (email addresses and the like) that have permission to see the content. By authenticating through OAuth you will be given an access token that will allow you to fetch the authenticated users email address. This can then be looked up against your user table to see if the user is registered and if your app enforces it, check whether the user has access to the page requested.
OAuth is proving that this person is the owner of the Google/Facebook/Twitter/Github Account. You can use this knowledge to sign someone in against a database of "local accounts" based on email used at sign up, assuming you validate the email on sign up locally.

OAuth - What information can I store?

I am running an ecommerce website and would like to make the website more accessible, hence I am thinking of using OAuth so they can login using some of their social media profiles. I also send out a lot of marketing campaigns to my customers via email and other methods, so at the moment when a user signs up I have some information such as their email and some details about their occupation (relevant to the products, don't worry I am not being nosy!).
If a user signs in using OAuth, then they won't be providing me with some of this basic information such as their email, as they don't have to use a signup form.
So, when implementing OAuth, I want to know what data I can store to my database about the user? At the moment I can send a newsletter to all of the users on my website for example, but with OAuth is something like this possible? What kind of information can I access for each user if they are signed in using OAuth?
Sorry if these questions have been answered elsewhere, I have been trying to search around but haven't found anything about what the company can gain, I've only found the advantages and disadvantages from a basic coding point of view and from a user point of view.
Thanks!
Using OpenID Connect, which is a standardized extension profile of OAuth 2.0 you can authenticate users through 3rd party providers. There are also a number of providers out there that have created their own proprietary extensions of OAuth 2.0 that gives them login semantics, but they are not standardized and your client code would have to deal with each of these proprietary extensions. It can be expected that all providers using proprietary OAuth 2.0 extensions for login migrate to OpenID Connect in the future.
OpenID Connect (and also the proprietary OAuth 2.0 extension protocols) do not just authenticate users but they also provide user identity information in the form of claims (or: attributes). So they do provide the basic information that you are looking for (e.g. e-mail) if only the user consents to giving it to your client. You can use that information and store it in your database for offline access.
The benefit of OpenID Connect is that it has standardized a number of basic claims so that your code can be provider agnostic when dealing with user info. See http://openid.net/specs/openid-connect-core-1_0.html#StandardClaims. The proprietary OAuth 2.0 login protocols do not provide standardized claims so you need custom handling (mapping/translation) per provider.

How to "pre-authenticate" another user with Windows Azure Access Control?

I'm trying to use Windows Azure Access Control to avoid the security risks in using usernames/passwords in my app and to simplify the authentication. However, this is a site that can be used by medium or large companies that may wish to "pre-authenticate" users. In other words, they may want to bulk create users by putting in the users' Windows Live IDs and create their accounts automatically, before that user has ever signed in through Azure ACS. I could accomplish this by sending that user an email with a link to a one-time-use page to create their account, but I am hoping to do something a little more seamless.
What I'm trying to do is equivalent to how Team Foundation Service (*.visualstudio.com) lets you add users to a team project just by putting in their Windows Live IDs and once you do, they can log in and access the project, even if that user had never signed in to TFS previously.
What I don't understand is how to do that using ACS and System.IdentityModel. I can use the nameidentifier claim to uniquely identify a user, but how do I get a nameidentifier for another user through a given provider?
I'm sorry if I'm not explaining this well, so feel free to ask questions.
Not really an answer but just wanted to share my thoughts on the issue.
The problem with ACS and Windows Live authentication is that ACS never returns the user's email address. All we get back from ACS is a token telling me that the user is authenticated. This token is created based on your ACS realm (i.e. if you change the ACS realm, a new token will be created by ACS for the same user). Again, the admins of the company who are using your application can enter the email addresses of the user but there's no way to get that email address back from ACS.
Just thinking out loud :), there're a few things you could do:
You use ACS for authenticating the user and then use Windows Live REST API to get more details about the user using the token sent by ACS. By using Windows Live REST API, you can get more details like name, email address etc. about a user. Or you could use just Windows Live API for authenticating the user. I'm not 100% sure but I think this is what Team Foundation Service does. Do take a look at http://zud.io as it does the same i.e. uses Windows Live API.
Another idea would be to create some sort of invitation tokens. In this approach, admins would "invite" folks. They would create invitation record by providing the name, email address of the users and the application would create unique invitation tokens. The application could then create an invitation link using which users would come to your application and authenticate themselves. Once authentication is done, you could look up the invitation record and retrieve user information from the database and create user record and associate the authentication token with the user record. The issue with this approach is that a user may not use the same Live Id as provided by the administrator. For example, I have at least 3 live ids and if I have that invitation link, I could sign with any of those live ids and the application won't be able to stop me from registering.
Yet another idea would be to use Windows Azure Active Directory (WAAD) instead of ACS. You could consume Graph API in your application to create new users for your clients. You're still not managing user names and passwords as that is done by WAAD. The two issues I could think of there are - a) As an end user, I have to remember one more username/password combination and b) At the time of login, I have to provide my credentials in myusername#yourtenantname.onmicrosoft.com which to me personally is a big hassle.
We too have been going through the same pain and for now we have decided to go with approach #2.
Hope this helps.

What is token-based authentication?

I want to understand what token-based authentication means. I searched the internet but couldn't find anything understandable.
I think it's well explained here -- quoting just the key sentences of the long article:
The general concept behind a
token-based authentication system is
simple. Allow users to enter their
username and password in order to
obtain a token which allows them to
fetch a specific resource - without
using their username and password.
Once their token has been obtained,
the user can offer the token - which
offers access to a specific resource
for a time period - to the remote
site.
In other words: add one level of indirection for authentication -- instead of having to authenticate with username and password for each protected resource, the user authenticates that way once (within a session of limited duration), obtains a time-limited token in return, and uses that token for further authentication during the session.
Advantages are many -- e.g., the user could pass the token, once they've obtained it, on to some other automated system which they're willing to trust for a limited time and a limited set of resources, but would not be willing to trust with their username and password (i.e., with every resource they're allowed to access, forevermore or at least until they change their password).
If anything is still unclear, please edit your question to clarify WHAT isn't 100% clear to you, and I'm sure we can help you further.
From Auth0.com
Token-Based Authentication, relies on a signed token that is sent to
the server on each request.
What are the benefits of using a token-based approach?
Cross-domain / CORS: cookies + CORS don't play well across different domains. A token-based approach allows you to make AJAX
calls to any server, on any domain because you use an HTTP header
to transmit the user information.
Stateless (a.k.a. Server side scalability): there is no need to keep a session store, the token is a self-contained entity that conveys all the user information. The rest of the state lives in cookies or local storage on the client side.
CDN: you can serve all the assets of your app from a CDN (e.g. javascript, HTML, images, etc.), and your server side is just the API.
Decoupling: you are not tied to any particular authentication scheme. The token might be generated anywhere, hence your API can
be called from anywhere with a single way of authenticating those
calls.
Mobile ready: when you start working on a native platform (iOS, Android, Windows 8, etc.) cookies are not ideal when consuming a
token-based approach simplifies this a lot.
CSRF: since you are not relying on cookies, you don't need to protect against cross site requests (e.g. it would not be possible to
sib your site, generate a POST request and re-use the existing authentication cookie because there will be none).
Performance: we are not presenting any hard perf benchmarks here, but a network roundtrip (e.g. finding a session on database)
is likely to take more time than calculating an HMACSHA256 to
validate a token and parsing its contents.
A token is a piece of data which only Server X could possibly have created, and which contains enough data to identify a particular user.
You might present your login information and ask Server X for a token; and then you might present your token and ask Server X to perform some user-specific action.
Tokens are created using various combinations of various techniques from the field of cryptography as well as with input from the wider field of security research. If you decide to go and create your own token system, you had best be really smart.
A token is a piece of data created by server, and contains information to identify a particular user and token validity. The token will contain the user's information, as well as a special token code that user can pass to the server with every method that supports authentication, instead of passing a username and password directly.
Token-based authentication is a security technique that authenticates the users who attempt to log in to a server, a network, or some other secure system, using a security token provided by the server.
An authentication is successful if a user can prove to a server that he or she is a valid user by passing a security token. The service validates the security token and processes the user request.
After the token is validated by the service, it is used to establish security context for the client, so the service can make authorization decisions or audit activity for successive user requests.
Source (Web Archive)
Token Based (Security / Authentication)
This means that in order for us to prove that we’ve access we first have to receive the token. In a real-life scenario, the token could be an access card to the building, it could be the key to the lock to your house. In order for you to retrieve a key card for your office or the key to your home, you first need to prove who you are and that you in fact do have access to that token. It could be something as simple as showing someone your ID or giving them a secret password. So imagine I need to get access to my office. I go down to the security office, I show them my ID, and they give me this token, which lets me into the building. Now I have unrestricted access to do whatever I want inside the building, as long as I have my token with me.
What’s the benefit of token-based security?
If we think back on the insecure API, what we had to do in that case was that we had to provide our password for everything that we wanted to do.
Imagine that every time we enter a door in our office, we have to give everyone sitting next to the door our password. Now that would be pretty bad because that means that anyone inside our office could take our password and impersonate us, and that’s pretty bad. Instead, what we do is that we retrieve the token, of course together with the password, but we retrieve that from one person. And then we can use this token wherever we want inside the building. Of course, if we lose the token, we have the same problem as if someone else knew our password, but that leads us to things like how do we make sure that if we lose the token, we can revoke the access, and maybe the token shouldn’t live for longer than 24 hours, so the next day that we come to the office, we need to show our ID again. But still, there’s just one person that we show the ID to, and that’s the security guard sitting where we retrieve the tokens.
The question is old and the technology has advanced, here is the current state:
JSON Web Token (JWT) is a JSON-based open standard (RFC 7519) for passing claims between parties in web application environment. The tokens are designed to be compact, URL-safe and usable especially in web browser single sign-on (SSO) context.
https://en.wikipedia.org/wiki/JSON_Web_Token
It's just hash which is associated with user in database or some other way. That token can be used to authenticate and then authorize a user access related contents of the application. To retrieve this token on client side login is required. After first time login you need to save retrieved token not any other data like session, session id because here everything is token to access other resources of application.
Token is used to assure the authenticity of the user.
UPDATES:
In current time, We have more advanced token based technology called JWT (Json Web Token). This technology helps to use same token in multiple systems and we call it single sign-on.
Basically JSON Based Token contains information about user details and token expiry details. So that information can be used to further authenticate or reject the request if token is invalid or expired based on details.
When you register for a new website, often you are sent an email to activate your account. That email typically contains a link to click on. Part of that link, contains a token, the server knows about this token and can associate it with your account. The token would usually have an expiry date associated with it, so you may only have an hour to click on the link and activate your account. None of this would be possible with cookies or session variables, since its unknown what device or browser the customer is using to check emails.

Resources