What are the best practices for storing client creds when implementing an OAuth2 provider?
I can store access_token/refresh_token/auth_code as a salted hash (just like passwords) if I decide that every time client requests a new one I issue a new one. But in the case of the client_secret I need to be able to show it along the client_id on the app registration page, so I can't keep only the hash.
Thanks!
Lev
Using a machine generated client secret is only one of many means to authenticate a client application. I assume this is what you want to use in your service. In this case you already answered your question, you have to store the secret in plain text as long as you want to be able to communicate it to application developers at any time.
If this is not acceptable for you, consider choosing a different solution, such as letting the developer set the secret like you would do with a password, and never store the plaintext; or use a private/public key pair authentication scheme like MAC.
Related
My company has a website. Let's pretend that it's hosted at http://www.example.com. I have three apps that I need to build for different teams. Users will have different permissions, possibly different OAuth logins, per app. I'd like to host apps on domains like:
http://www.example.com/apps/my-first-app
http://www.example.com/apps/my-second-app
http://www.example.com/apps/my-third-app
My question is can I do this? I'm trying to understand if OAuth tokens are per domain or per app/url. Thank you for your help.
OAuth Tokens are indeed per domain / app / url.
I did read a while back you can create multiple tokens and store those in the db for the time being so that multiple users with multiple roles can use those tokens to do the things they are permitted to in one domain for instance. I cannot really remember where I read it, but once I do i'll get back to you as soon as possible
You should be able to have multiple consumer apps like that. I'm not sure providers would work however.
Each consumer has a unique client ID and secret (and usually a callback url on the provider, github say). As long as each consumer application has a unique client ID I can't see why this wouldn't work - just create 3 applications on the provider and then make you set the callback urls correctly.
I have two Rails apps using devise for authentication: a website and an API. Even though I'm the owner of these 2 apps, for many reasons, I wanted complete separation between the two. When a user signs up on the website, an account is automatically created on the API side. The biggest problem I have is keeping the users table in sync between the two apps. I ended up with a bunch of RESTful API callbacks on the website user model which create/update the API user.
The second part is calling the API on behalf of the user logged into the website. Problem is that I don't have the user's decrypted password so I can make the API call. All API calls use basic HTTP authentication. The passwords are hashed into the database and cannot be decrypted (which is a good thing, thank you devise). Because I keep all users columns in sync between the 2 databases, my website users encrypted_password column is identical to my API users encrypted_password column.
So, what options do I have for solving this? I'm thinking either modifying the API such that an admin call for each regular call takes an admin username and password and a user ID (to get that user's transactions for example). Or, implement a shared database between the 2 apps - but I have a lot of associations between users and other models... how would indexing even work?! Or, hijack the devise authentication and compare encrypted_password (from my website) to encrypted_password (to my API) - since they are the exact same; but this opens a security can of worms. Or, create keys authentication and generate unique GUIDs for users... but then that would be just as bad as having decrypted password stored in a database. I hate all these solutions. Perhaps someone has a better idea?
When you authenticate a user in Devise it takes the plaintext password and combines it with a pepper and passes it through bcrypt. If the encypted password matches the value in the DB the record is returned.
The pepper is based on your rails app secret. So unless the two apps have the exact same secret then authentication will fail even if you have the correct encrypted password. Remember that the input to bcrypt has to be identical to give the same result. That means the same plaintext, salt, pepper and number of stretches.
You're correct in that sharing the passwords back and forth is not a solid solution. You are also correct in that using UUIDs instead of a numerical auto-incrementing id is part of the solution.
What you can do is implement your own authentication provider. The Doorkeeper gem makes it pretty easy to setup your own OAuth provider (or you can use Auth0 if using an external service is acceptable).
The web app would use Devise + OmniAuth to authenticate users against the authentication provider and use the credentials returned to identify the user in the web application.
For the API application I would use Knock for JWT authentication. Where the API server proxies to your authentication server via the oauth gem.
However you should consider at this point if your web and API app really should be running on separate DBs. Keeping writes in sync across both DBs can be quite the task and your should ask yourself if your really need it at this stage.
JWTs would make it easy to include information such as user id right in the JWT without relying on external persistence such as a users table. Just ensure the token is correctly signed and don't store personal information in it such as email since usually JWTs are not encrypted but only signed.
I actually did a write up tutorial on this while back if interested.
https://www.moesif.com/blog/technical/restful-apis/Authorization-on-RESTful-APIs/
I want to secure my application with JWT. This application is only accessed by other server applications that know the secret key before hand. I do not need to add a token generation since the key is already known between the applications. I tried to find some samples for this, but all the examples are complicated (I'm new to spring security) and moreover they do not include anything simple that would fit my use case (known secret key and algorithm, so no provider and storing of the token is needed).
Basically what I want is to decode the token sent by the fellow server, check the secret key, check the sender and check the time (the fellow server will always generate a new token so if that token is stollen then it will be invalid in a small amount of time).
I've thought of implementing this with a custom filter (or interceptor) plus this library and remove spring security entirely, since I can't find any use for it. But I would prefer to use spring security in order to have it available for any future needs and in general achieve what I want by doing it the spring way.
The JWTFilter from JHipster may be a good start!
I am working on an asp.net mvc-4 web application and I have started implementing some web services which provides statistical information about my site. But to make sure that only authorized and authenticated consumers can call and consume the web services I am thinking of defining a master login username and password for each consumer, and when a consumer sends a web service request he should include these master login username and password (stored as a hash value ) in the web service calls.
For example the web service link to call specific web service from my web site will look as follow:-
/web/json/statistic/getsummaryinfo/areacode?j_username=masterusername&hash=D012B772672A55A0B561EAA53CA7734E
So my question is whether the approach I am following will provide a secure solution to my web services and to the consumers? OR my approach have security holes I am unaware of ?
:::EDITED::
I am using the WebAPI controllers to implement the web services inside my asp.net mvc-4.**
Best Regards
There are a few ways to make sure things are secure.
http://techcrunch.com/2012/11/08/soa-softwares-api-management-platform-and-how-it-compares-to-its-sexy-counterparts/ This article just came out today highlighting some API tools. I'm not sure how big you are or are planning to be, but if you're looking for scale, these tools seem to be pretty popular (note: I haven't had a large scale API project myself, so I haven't used these).
You can use something like ServiceStack to build your API layer. It has authorization and authentication built in with a boatload of authentication providers. It scales well and, after a call to authenticate, is session-based so you don't have to authenticate each call.
You can use "signed" requests. Signed requests often look something like: "take all the parameters for the request as a querystring, append a 'secret consumer key' to the end of the request', and then sign the request by appending the md5 hash of the results (without the secret key!!) to the request." This is a safe way of doing things because even if the request is made client-side (AJAX) it is generated server-side using a secret key. So you can ensure that things weren't tampered with.
You can go the oauth/token route (which often still uses method #3 above).
You can go with a simple API key that can be revoked (again, fotne used with method #3). bit.ly uses this method I think.
Option #2 is my favorite. I like ServiceStack. But to be honest the learning curve for your first project can be a little steep.
A master username and hashed password feels weak to me, so I'd strongly consider at least looking around at how others are doing it.
HTH
I do not consider your way to be safe. If I could listen on the wire and cache the request I will have the login an the password to the service. There even does not matter if the password is hashed or not. I like the point 3. in Eli Gassert's answer. It sounds very useful and light weight and you are not exposing the password because it is hashed "somewhere" in the request.
I'm just starting reasearch about the best way to implement user authentication within my soon-to-be app.
This is what I have so far:
A desktop (Windows) application on a remote server. That application is accessed locally with a browser (it has a web console and MS SQL Server to store everything).
The application is used with local credendials stored in the DB.
This is what I'd like to accompllish:
Provide access to some information on that SQL Server DB from my app. That access of course must be granted once a user has id himself with valid credentials.
This is what I know so far:
How to create my PHP web service and query info from a DB using JSON.
How to work with AFNetworking libraries to retrieve information.
How to display that info on the app.
What I don't know is which could be the best method to implement user authentication from iOS. Should I send username and password? Should I send some hash? Is there a way to secure the handshake?
I'd for sure appreciate any advise, tip, or recommendation you have from previous experience.
I don't want to just implement it but instead I want to do it as good as possible.
There have been books written on this, so any answer given here is necessary incomplete. So, I'll give you an outline of the simplest thing that actually works. The bare minimum for securing a service like this is to use HTTP Basic Authentication (supported natively by both AFNetworking and PHP) secured by SSL/TLS.
Basic Authentication is a way of hashing (not encrypting) credentials in a standard way and sending them as one of the headers in your request (Authorization: Basic <Base64-encoded concatenated credentials>). AFNetworking supports this as part of its AFHTTPClient class (see the -setAuthorizationHeaderWithUsername:password: method). PHP parses the authentication header into a pair of server variables ($_SERVER['PHP_AUTH_USER'] and $_SERVER['PHP_AUTH_PW']). From here, you just check the username/password combination against your user database and allow or forbid access to the resource.
The reason it's crucial to pair this technique with HTTPS is that the credential hash is easily reversible; you're basically sending the password in the clear, so it can be grabbed by anyone listening to your traffic. Setting up a certificate and sending your requests over the secure channel prevents this type of vulnerability.
If you want to be a little more sophisticated, two-legged OAuth is also a viable choice for this scenario.