I am new to Oauth2 and hello.js and don't understand, how to use it securely.
I was trying singup/login with Google and for me the problem is, that 3rd party Oauth service (e.g. Google) does not return user-details (email, id) to my server. The critical data (id, email) is fetched on the client and then it can be sent to my server by client / browser.
But I cannot make reliable server API which receives arbitrary network-type(google|facebook), userId, password and makes login / signup according to this. Everyone could then register as someone other's = arbitrary social id.
What workflow would You sugest to create an account for Google-authenticated user, in my server?
Edit: sorry, this whole queestion is probably my misunderstanding of Hellol.js purpose.
In my case, I need something like authom or passport.
Google adds to the url all the information about user, and there is no secret token
It should only be adding an 'access_token' this is unique session token to make subsequent calls to googles api's on behalf of the user.
Related
Let's say I'm trying to build a web application using Vue.js where an end user uses a form to subscribe to a newsletter.
The frontend is a Vue app, the backend is a PHP REST API.
The API requires Basic Auth authentication.
In the frontend I'm calling the API using axios:
axios
.post('localhost/api/v1/subscriber.php', {
// I know the data is missing but this is not what the question is about..
auth: {
username: 'USER',
password: 'PASS'
}
})
Everything is working fine, except that Vue.js is JavaScript and therefore visible on the client side (right click -> Inspect/ View page source) and every end user can see the username and password.
What's the best practice for "storing" the password (and username)?
Even if PASS was the hashed password, the end user would still be able to use it to to an API call by himself...
From my point of view you have a fundamental design issue with your API. As it seems you want to expose some global credentials to the frontend so the SPA can in turn authenticate against the API. This approach is strange: either the endpoint is public and therefore should not need authentication or it is protected and each user should authenticate properly.
If you just want to protect the API against spam bots etc. you could send a nonce to the app and check for it in the subsequent request. This by no means is a robust protection but makes sure that each POST requires a GET and some parsing on the spammer's side.
If you want your users to be authenticated across multiple requests you should use well established methods to provide a session or a remember-me function. This could be e.g. session cookies (works but is vulnerable against CSRF attacks), JWT (with or without OAuth) or something similar.
But whatever you do: don't try to obfuscate shared credentials you pass around!
As a best practice, you shouldn't store password. You should create a JWT token on the backend when the user logged in or signed up. Then you can store the JWT token on your front-end(local storage) when you received the token from the back-end.
Easy Way to Encryption,
You can encrypt your password with any encryption algorithm on client-side then decrypt on the back-end with the same key.
Hard Way to Encryption,
As a hard way, for security reasons and security best practices, you should encrypt all your request end to end. Otherwise, anyone can access the user's information on public networks.
The below link includes all detailed information about the end to end encryption
https://medium.com/#weblab_tech/encrypted-client-server-communication-protection-of-privacy-and-integrity-with-aes-and-rsa-in-c7b180fe614e
You can store your Authorization header values in localStorage or sessionStorage.
Use interceptors to include the header values for each of your request
Here is sample:
axiosInstance.interceptors.request.use(function (config) {
const token = localStorage.getItem('token')
config.headers.Authorization = token
return config;
});
The value of Authorization header, stored in LocalStorage, will be automatically each time you make HTTP requests.
Note: Replace the variable token with username and password
I have an app and I want to let people login using google sign-in. I need to check in the server what are the permissions of the current logged in user. (I have a table with email/role)
I read the documentation here:
https://developers.google.com/identity/sign-in/web/sign-in
from what I understand, when a user logs in using google, I get a callback and I can use the email and make calls to my server with it.
But what I don't understand is how can I make sure a malicious user won't see the javascript code and make a request to my server using any email he wants?
In other words, if the entire sign-in is in javascript, how can validate the identity in the server?
Assuming that you are doing the following:
Signing in from the Web
Using JavaScript for Sign-in and all data access
The following measures preventing malicious 3Ps from making API calls using your credentials / other user credentials:
API calls are domain-restricted to the authorized origins you configured in the developer console
API calls are restricted to the current credentials (e.g. only can get current user details / can only get credentials and tokens for the current user)
That said, let's move on to authN: making sure the user is who they claim to be. On the sign-in callback, you will receive a special token, the ID token, that has:
The audience for the token (your client ID)
The issuer of the token (user ID from profile)
An issued timestamp
An expiration timestamp
etc..
These values are used to prevent forgery and avoid the confused deputy problem. For example, you use these values to check claims of who the user is, that the issuer of the token was you, and that the token has not expired. You also look at the ID token signature and validate it either using JWT functionality or by passing it to the Google verify token endpoint.
After verifying the user using the ID token, you can set a cookie for establishing a session and avoid having to verify the user on every API call.
Google provides token verification samples here, for example, the Google+ Token Verification sample in Ruby. Additionally, the Google+ quickstart samples demonstrate establishing a client-server session in the "/connect" server endpoints on the server-side languages (Ruby, Python, .NET, etc).
Additional discussion on the topic is available in the Identity Cookbook.
I'm running a webview from a cordova app and want to authenticate a user, I know they have the OAuth strategies but I need to use the email/password combination.
I'd like to keep things simple but may end up having to generate a token.
Open an InAppBrowser that loads an auth flow for firebase
Listen for that auth flow to be completed using this method: http://blogs.telerik.com/appbuilder/posts/13-12-23/cross-window-communication-with-cordova%27s-inappbrowser
Grab the result from the webview again and insert it into the webview firebase instance
I'm guessing that's not possible due to security.
My app is using Amazon login (required) so my alternative would be:
webview loads InAppBrowser with our external url
that loads Amazon auth, then generates a token for Firebase
webview listens for token and grabs it, stores it in localstorage
Edit:
In the firebase docs on logging in with a username/password, I see it returns a token for the session and more information in the authData object:
https://www.firebase.com/docs/web/guide/user-auth.html
Could I then take all the information from that object and send it back over to the cordova webview and then populate that Firebase ref with the information?
Some answers from the wonderfully helpful support at Firebase:
First:
You’re correct – anyone can make a request to sign up, and we don’t expose any capability to secure the url which people can sign up from for email / password authentication.
The main reason that we require / enable origin whitelisting for OAuth authentication, but not for email / password authentication, tends to revolve around sessioning.
The Firebase login server does not maintain sessions (via cookies or any other method), and so requests to the login server for password auth. requires a user credential (the password) for every request. CSRF is typically a risk when a malicious party can take advantage of a user’s session browser, i.e. make requests on behalf of the user to some page where cookies are automatically sent by the browser.
Furthermore, we don’t have a great way to actually do ideal origin-based whitelisting for these pure HTTP requests. We could use CORS, but would have to fall back to JSONP for older browser environments that don’t support it. To complicate matters further, PhoneGap / Cordova apps don’t have the same notion of an “origin” at all, and from the perspective of a server – the calls are indistinguishable from any malicious party making an HTTP request with the same headers.
The OAuth providers, however, use cookies for sessioning and do not require user invention for each auth. request. If you’ve approved a particular Facebook app, you won’t be shown any UI/UX or be prompted the next time that app requests your data – it will be invisible. When we do OAuth, we never have to send any user credentials to Facebook / Twitter / etc., because those are stored in browser cookies for facebook.com / twitter.com / etc. What we need to protect is a malicious party pretending to be a popular, valid Facebook app. and taking advantage of that short-circuit behavior that would get access to user data without the user’s knowledge.
My response:
So, how is that secured? If anyone can make a request to sign up from a
cordova webview (which comes from no specific url, just the app iteself)
then I can't secure from which url people can sign up from? So any site
could use our url "xxx.com" in their config and start registering
users?
That doesn't seem right to me.
I think I still need to have an external url that is whitelisted by you
guys. That would have the login form and do the auth.
But then my question is, can I transfer that auth back to my cordova app?
Is it somewhere in localStorage I can check? I'll have to run some tests.
And final response:
Sure thing – we’re happy to help. I wrote much of the original client authentication code, and can speak to the design decisions and rationale that went into it. Be sure to let me know if you have further questions there.
While we don’t store user passwords in cookies, of course, we maintain a Firebase auth. token in LocalStorage. Our authentication tokens are signed by your unique Firebase secret (so they cannot be spoofed), and can contain any arbitrary user data that would be useful in your security rules.
By default, and when using the delegated login (email + password) service, these tokens will only contain a user id to uniquely identify your users for use in your security rules. For example, you could restrict all writes or reads to a given path (e.g. write to /users/$uid/name) by the user id present in the token (“.write” = “$uid = auth.uid”). Much more information on that topic available on our website.
Your plan to spin up a server to authenticate users with Amazon and generate tokens sounds correct. This is a common pattern for our users who wish to use authentication methods that we don’t support out-of-the-box (ie Amazon OAuth) or have custom auth requirements. Note: once you’ve created those tokens and sent them down to the client, they’ll be automatically persisted for you once you call ref.authWithCustomToken(…). Subsequent restarts of the app will use the same token, as long as it has not yet expired.
This is a topic of interest to me too as I have implemented something similar , twitter digits (native android) + firebase custom login in webview.
I think, as recommended by firebase, you can use other authentication providers and then the firebase custom login.
Do you use the Amazon login in android native code ? If so after login, then generate a JWT token for firebase and use it to access firebase.
If all code is in Html/js app, then maybe you can use custom login and generate a token on your server after making sure its logged in to the Amazon.
The trouble with Android hybrid apps is the following: the JWT token (for firebase) should be created on secure system (eg. server side) not with android java code, other option for hybrid app is to do a http request to generate the token, but I find that less secure, anyone would be able to get a token by finding the URL, than I resort to generate token within android app code, you can change security key/seed for token when doing new releases.
In summary, I don't think firebase studied the problem of mobile hybrid apps.
I know the issue of securing connexion between a JS app (let's say just 'app') and an OAuth2.0 server (let's say just 'server') is an age-old question.
However, I can not find a lot of information about the special case where the app and the server are coded by the same entity and stored at the same place (i.e. same domain, or at least, two subdomains of the same domain).
First of all, as far as the OAuth grant type is concerned, I think the right one is the Resource Owner Password Credentials Grant, since the server and the app have the same author. The issue here being that the Client ID and Client Secret are available to the user in the client. This can be dealt with either by developing a proxy on server end or by using short-life tokens and disabling CORS (if I understood correctly). Is there any other property we can take advantage of as far as security is concerned when server and app have the same author?
My second question relates to the optional use of a Facebook Login authentication (or whatever well-known app OAuth login system: Google, Twitter, etc.).
Ideally, I want users to log in using either:
My-app-related credentials (if they registered without using FB login option)
Facebook credentials (if they registered using FB login option)
The first log in method is the classical one: upon log in, are sent to the server the user credentials along with the client ID and client Secret, we get back an access token and everything works well.
I must confess I'm a bit lost with the second method: upon login, user Facebook credentials are sent to Facebook server, which responds with an access token, and my app get access to my user Facebook information (such as email address and UID). But I do not know what to do with this FB information, and especially what I should sent to my own OAuth server so that:
The user gets connected to my server
The connection is secure (i.e. no one can impersonate the user by only having to get her Facebook UID for instance).
In other terms, there should be something secret related to Facebook sent to my server but I can not figure what.
I have found the answer to my second question, so I share it here:
What should be passed on to the server is the Facebook access token, so that the server can :
make a request using Facebook PHP SDK and the given token
retrieve user data (such as Facebook UID for instance)
match it against your website user database (which should have users FB UIDs)
actually connects the user if there is a match
Step 1. and 2. can be done nicely with the helper class FacebookJavascriptLoginHelper of the FB PHP SDK. In this case, the access token is stored by Facebook Javascript SDK into a cookie that is read server-side by the FacebookJavascriptLoginHelper.
I would like to access a user's Outlook emails with my javascript app.
Google makes this very easy using Oauth and it's restful Gmail API.
I have tried researching similar options for Outlook, but I can't seem to find a good way to authenticate a user with Oauth 2.0, then access their message inbox.
Are there any Microsoft technology experts that can point me to some resources to get started here?
I am restricted to using only client-side code as this is for a phonegap mobile application. I would like to continue using oauth-io but I realize that may not be an option.
I was having a hard time tracking down the process for getting the emails as well. Anyway, first things first, you'd need to register your app for OAuth here. This page describes some more details on the registration and also how to access the needed API.
Although you can do the calls via Javascript, there are some security issues because you'd eventually need to send your client secret. It might be safer to do some parts in the server side.
First step is getting the user to login and retrieving the access token.
https://login.live.com/oauth20_authorize.srf?client_id=[CLIENT_ID]&scope=wl.imap wl.offline_access&response_type=code&redirect_uri=[REDIRECT_URI]
On the server side, exchange the access code for an access token:
https://login.live.com/oauth20_token.srf?client_id=[CLIENT_ID]&client_secret=[CLIENT_SECRET]&code=[ACCES_CODE]&grant_type=authorization_code&redirect_uri=[REDIRECT_URI]
Get user's email and other account info (Python sample codes):
https://apis.live.net/v5.0/me?access_token=[AUTH_TOKEN]
Retrieve emails via IMAP using the email address from emails>preferences in previous reply (see more details here). It would look something like this in Python:
import imaplib
mail = imaplib.IMAP4_SSL('imap-mail.outlook.com')
username = [username]
access_token = [access_token]
auth_string = 'user=%s\1auth=Bearer %s\1\1' % (username, access_token)
mail.authenticate('XOAUTH2', lambda x: auth_string)
mail.list()
You can look at existing IMAP libraries to retrieve the actual emails from there. Here's one for python.