I need Oauth2 or similar, the problem is that it seems I need third party systems for implementing Oauth2, like google, and I don't want that. I want to be the one to create and give permissions to the client.
Further explaination:
I, the server, want to offer a service to the client.
I want to authenticate the client, to give him different permissions about my service.
Client authenticate with username and password, or clientid and secretkey, or whatever.
Then I, the server, create a token and give it to the Client, who will use my service forever or until I decide he lost that privilege.
The token is what I use to know who he is, that grant access to my service but is also revokable.
I tryed to understand oauth2, jwt tokens and much more, but I didn't understood much and, when I did, I found out that wasn't secure at all.
So I beg you for help, what one in my situation should do?
Related
So these days I was reading about OpenID and OAuth2. I've seen some questions (this and this), but from what I've read you can use OAuth and for authentication, not just for authorization. On the second question, I've read this:
If you have an account (with some private resources) in a website, you
can log in with username/password couple. If an application would like
to get some private resources, and if you don't want to give them your
username/password, use OAuth.
But if you want to log in into multiple websites with a unique
account, use OpenID.
This raised more confusions (Dominick Baier said in one of his presentation that if you haven't heared about OAuth2 these years, you were living in a cave for the last years, so it seems this was my case): If I have many webservices (API's) and if I have an STS service to request tokens for all the API's then I am using OpenID? Is OAuth is not scalable to extend the authorization to multiple sites using a single STS service?
When you try to explain me, please consider that I haven't implemented an authentication or authorization process before.
You are right: lot of authorization servers based on OAuth2 provides a way to authenticate. But OAuth2 is not designed for that purpose.
In an OAuth2 context, the client has just an access token to retrieve/manage resources on a resource server. It knows nothing about the resource owner.
That is why the OpenID Connect protocol has been created. It works on top of the OAuth2 Framework protocol and allows the client to get information about the resource owner.
I recommend you to look at this very interesting talk (start at 4:44). This video helped me a lot to understand the purpose of each token. I hope it will help you too.
I've been reading a fair bit on Microservices recently, and especially around AuthN and AuthZ. For the most part, this all makes a lot of sense, and I can see how it all should work.
For what I'm playing with, I going with delegated authorization - so I'm to be passing tokens around from client to service, and then passing the same token on from service to service. I also have an endpoint on the OAuth2 Service that will accept a token and return the details of the token - the User ID, the Start and End of the validity period, the scopes that the token is valid for, etc.
The problem that I'm running into here is - in order to correctly issue a token, there needs to be some communication with the User Service to ensure that the User that the token is for is actually valid. And in order to verify a Token, there needs to be some communication with the User Service to ensure that the User is still valid. And yet, in order to safely communicate with the User Service to get details about a User, a Token is needed that gives permission for this access.
I assume there is some standard practice on how to solve this circular dependency between the OAuth2 and User Service, but I've not seen any mention of it at all. Is this a common problem? Or have I just missed something obvious?
(Note - for now I'm only implementing Client Credentials Grant and Resource Owner Password Credentials Grant, since I'm only playing around to see how it all works and they're easier to call with cURL. I don't know that this makes any difference though)
Yeah, that's a bit of a chicken and egg problem. Not sure how much control you have over the authorization server, but one way of solving this issue is to secure the call to the user info service using client certificates.
Another is to combine the user info service and authorization server into one service and eliminate the need for the call all together.
I have a question regarding how I should architecture a REST API using access token and API keys.
I have an API that needs authentication. I want to enable two use cases:
The user logs into the interface using OAuth2 (password grant), and is granted a temporary access token. This token is used to authenticate the user. Therefore, the UI, that itself using the API, can fetch data and display it.
I also want the user to have an API key to do the same calls, but in its application. Obviously, contrary to the access token, I want the API key to be long lived. Also, contrary to the access token that is tied to a given user (if we introduce a team mechanism, each user will have different access token, although they access the same resources), the API key should be unique to the project.
While similar, I'm not sure about how should I architecture that. I think that, internally, both API keys and access tokens should be stored in the same table, but API keys having no expiration time. Am I right?
One thing I'm not sure also is the concept of client. It seems that in the spec, the client is more like an external application. However may I actually use this concept here?
For instance, each "project" is actually a different client (although the client here is the same application, not an application created by a third-party developer).
Therefore, if user A creates an account on the system, a client A will be automatically created, with an access token tied to the client A, with a long-lived access token (aka API key). This can be used to perform API calls directly on his code, for instance.
Then, if user A logs into the dashboard, a temporary access token will be created, but this time with no application, but tied to the user, with a short life.
Does this sound sane? Have anyone already implemented such a thing?
Thanks!
I think you should not consider the "API keys" a substitute of the access token.
You will have to use an access token anyway to bear the authentication between requests, so what you're actually modelling with your "API keys" is not a replacement of the usual bearer token, but rather a different client that provides other grant types to request a token with.
The flow I'd personally implement is the following:
The user authenticates with the password grant type with a common client for every user (i.e. your "web app" client, which is public, i.e. it doesn't have a client_secret).
The user can then create its own client. As per OAuth2 specs, these are not public, so they will consists of a client_id and a client_secret. These are what you call "API keys".
A user will then be able to request an access token via their client, with any given grant type you want to support (e.g. direct client credentials, authorization code, implicit, third parties, etc.). You will have to stress quite a bit about the due safety practices on how to handle the client credentials.
Obviously, you will have to implement your OAuth2 server in such a way that clients can belong specific users, and have different acceptable grant types (i.e. you may not want to allow the password grant usage with a user client, while you may want to disallow any grant type other than the password one for your web app client).
You will then be able to define tokens TTLs, or lack thereof, on a per client or per grant type basis (e.g. access token requested via password grant, only usable by web app client, will have a short TTL, while authorization code grant will provide long lived tokens).
I would advise against complete lack of TTL, though, and rather use the refresh_token grant type to renew expired access tokens.
Furthermore, you'll probably have to define an authorization system of some some sort (ACL, RBAC, whatever), to define which client can do what. This means each access token should contain a reference to the client used for its creation.
So, to sum it up, here are the relations:
User has a Client.
Client has a User.
Client has many Token.
Token has a Client.
Token has a User.
YMMV on bidirectionals.
You should be able to implement everything I described with the most common OAuth2 servers implementations of any given platform.
TL;DR: "API keys" are actually OAuth2 clients.
I wrote a post about the way to use access tokens for RESTful applications: https://templth.wordpress.com/2015/01/05/implementing-authentication-with-tokens-for-restful-applications/. Perhaps can this give some hints.
To answer your questions, I think that we need to have something homogeneous. I mean all your authentication mechanisms should be based on access tokens. Your API keys would allow you to get an access token that would be actually used for authentication.
As far as I understand, you have two kinds of users of your applications:
End-users using the Web UI (login with password through OAuth2)
Applications (login with API keys)
So I would implement these two kinds of users and make them the ability to get access tokens. Access tokens will be used in both cases to access the RESTful services.
In addition, I think that this answer can give you some other hints: Securing my REST API with OAuth while still allowing authentication via third party OAuth providers (using DotNetOpenAuth).
Hope it answers your question.
Thierry
Thank you for your answer.
I'm actually quite experience with OAuth2 itself, my question was more targeted to API keys. I like the idea of an API key exchanging an access token but I think that does not work. The API key is fixed and does not change, while the access token can expires.
The question is: how the app can know if this is an access token or API keys. I mean, ok, let's say that in my database, each user has an "api_key" column in their database.
Contrary to an access token, the api_key does not expires (although the user can eventually rotate it). What I want, as I told, is homogeneous handling of authentication.
Case 1: my own web app do API calls
The workflow is as follow, using OAuth2:
User enters his mail/password.
Authorization server returns a temporary access token (eg.: "abc").
In the web app, all API calls are done using this token. For instance: "/payments/1" with Authorization header: "Bearer abc".
Nice and simple.
Case 2: the user has an API key, that does not expire and can be used privately in their own app
Obviously, the authorization mechanism must stay the same. So:
User goes into his account, and read that his API key is "def".
In their server code, they can do the same call, with same authentication mechanism. So he can call "/payments/1" with Authorization: "Bearer def".
And it must work. As you can see, nothing has changed in both examples. They access the same resource, same authorization mechanism... but in one case we have an access token and in other case we have an API key. And I have no idea how I should implement that both from a database point of view and in the authorization code.
One potential idea I had is using different auth mechanism. For OAuth, it would be "Authorization: Bearer accessToken", while for API it would be a Basic authentication: "Authorization: Basic apiKey".
Does this sound good?
I want to use 3rd party authentication (OpenID, maybe OAuth but I guess OAuth is meant for authorization) so that user can login easily.
But does authenticating on every request means I call the 3rd party (eg. Google) many times even if I don't need any thing from it? For example, I use OpenID authentication but the API I use is something internal (eg. /api/tasks/add).
Let's fix understanding issues first. OpenID and OAuth are a bit different. There is a simple way to memorize that different:
OpenID is for humans. Simple example: you want to skip boring registration step and let user reuse existing account.
OAuth is for services/robots. Simple example: you want your script to access external API with some user's data.
There is a simple explanation provided by wikipedia:
Note that with OpenID, the process starts with the application asking
the user for their identity (typically an openid URI), whereas in the
case of OAuth, the application directly requests a limited access
OAuth Token (valet key) to access the APIs (enter the house) on user's
behalf. If the user can grant that access, the application can
retrieve the unique identifier for establishing the profile (identity)
using the APIs.
So I want to use 3rd party authentication ... that user can login easily. would probably mean you are going to use OpenID.
Answering your question: you do not need to call any third-party services on any request. It will be very inefficient and slow. OpenID provider will return user's credentials and you are good to go.
Please make sure you have identified requirements correctly.
OpenID Connect is an authentication mechanism written on top of OAuth2. The client obtains a bearer token that it can send in an Authorization header with each request to the resource server.
This ID Token is a JWT, signed by the OpenID provider. A decoded token looks something like this:
{
"iss": "https://server.example.com",
"sub": "24400320",
"aud": "s6BhdRkqt3",
"exp": 1311281970,
"iat": 1311280970
}
So it can be verified by the resource server without needing to contact the OpenID provider. The OpenID provider has a User endpoint where the relying party can fetch more detailed user info that is not included in the token, such as name and email address.
I believe both the answers by Renat Gilmanov and flup should be useful to you, but I will try to just answer the question that was asked, here.
No, it does not mean you contact the 3rd party site on every request. In fact, you can't, since the whole OpenID process should just happen once for a given session (it's a somewhat annoying manual step for the user)
I'll refer to the OpenID provider (3rd party) as Google, since that's the example you gave in the question.
The only thing that Authentication will do for you is give you Google's assurance that the person making that particular request also knows the password to the Google account name they gave you.
After that, it's up to you to keep track of requests coming from the same "person" and treating them as the same account. Basically, however you're handling the rest of the user's "session" information, you can now assume that all requests in this session are from that user.
The most common way would be through passing a cookie to the browser immediately, which contains some identifier that you keep track of on the server, and that confirms for you that whoever passes you that cookie is also the person who knew the password for that Google account. Another option would be sending custom HTTP headers, which is preferable in certain ways, but trickier to do by hand.
You could build all of this manually, but I would very strongly recommend finding some library code to take care of as much of this for you as possible. You don't mention what you're using to build this Web Application (in fact, you don't explicitly say it's a web application, I just gleaned that from the way the question is tagged), but there are plenty of choices for pretty much every framework or system you're likely to be using.
On some level, everything I wrote applies if you're writing an API for a native mobile app to connect to, as well. But you may have to jump through some slightly more complicated hoops in order to have the user authenticate, since some OpenID providers assume you're coming through a web browser.
Suppose I have a front-end application that wants to fetch some data from a back-end service. (I do.) The service will need to verify that the end-user is authenticated, that it is authorized to use the service and possibly filter the returned data based on the user's privileges. In my case, both the front-end app and the back-end service relies on Azure ACS for authentication.
Ideally the front-end would like to act on the behalf of the authenticated user, which sounds like a good fit for using an ActAs token (as specified in WS-Trust). However, it turns out that ACS does not currently support ActAs.
A workaround could be to use the actual bearer token (the bootstrap token in the front-end app) to authenticate to the back-end service. It's not hard to do, but would it be a bad idea for some reason?
From your front-end app, you could certainly pass along the identity data of the end user by either sending the token as is or sending the attributes from it. Both have issues. For the former, if it's also encrypted, the front- and back-ends will have to share the private key needed to decrypt it; they will also have to share audience restrictions, etc. in order for the back-end to consider the token valid for it. In other words, the front- and back-ends will be ONE relying party, not two. Might not be a problem, but be aware. In the latter case, you end up sending user data in a proprietay way which could increase integration and maintenance costs over time. In both cases, you can authenticate the front-end app to the back-end using some other type of credential, e.g., a certificate used at the transport level and, thus, forming a trusted subsystem between them.
One thing that I would suggest you consider instead is OAuth 2. From this blog post, it seems to me that ACS supports it (though I don't have any first hand experience w/ it). The truely wonderful thing about OAuth 2 is that it bakes delegation in, and is NO WHERE near as complex as ActAs in WS-Trust. The net result is the same, i.e., the back-end service will have info about the calling service and the end user, but the amount of effort to get it setup in incomparable. The tokens will still be bearer tokens, but you can mitigate that to a degree by using SSL. Beyond SSL, you can put some additional measures in place, but the best, IMO, would be if Microsoft did something in ACS like Google has done w/ their Access Tokens for service accounts which uses asymmetric keys that are chained up to a PKI. (BTW, for all I know, Microsoft may have already done something like that; if so, you're set.)
Anyway, HTH!