So I'm trying to access my own data from an external app via their API. I only need access to my own data. Not trying to receive data from any of my users' accounts, so they don't need to authorize anything. So obviously I need to avoid any redirects (which seems to be the standard process the more I research OAuth...)
The process is hit the /authorize endpoint, which returns a code. Then provide that code in a request to the /token endpoint. Which then allows me to access my account via the API. I'm 95% sure this process is standard for all OAuth, but figured I'd provide details in case it's not.
How do I provide credentials on the back end to get a code to enter into the request for a token, so that all user interaction is negated? The API I'm using forces me to use OAuth.
The oauth2 grant you are describing is called Authorization Code Grant. This way of authentication has been designed so that applications which want to access resources of a user do not have access to the users credentials.
So if you found a way to interact with the user credentials in this grant it would be considered a hack.
If you do not want the individual user to enter the username and password but you want to access the api with a kind of "system account" this is not the oauth grant you should use.
There are multiple grants that would work for you. The question is which are supported by the authorization server and available to you.
Resource Owner Password Credentials Grant
This grant type is suitable for clients capable of obtaining the resource owner's credentials.
However
The resource owner password credentials grant type is suitable in
cases where the resource owner has a trust relationship with the
client, such as the device operating system or a highly privileged application.
It is very likely that this grant type is not avaiable as it could be misused to steal user credentials.
Client credential grant
The client can request an access token using only its client credentials.
How the resources are tied to a client is not part of the oauth specification and therefore provider specific.
If you want to read more about oauth2 here is a good article.
The Oauth 2 grant flow that you're describing is the Authorization Code Grant Flow, like NtFreX's answer says. And like they say, if you have the option of using one of the above two grants with that API, that's the easiest solution.
However, if you don't, there's still a way to avoid "user interaction". It's unclear what you mean by "user interaction", but in the Authorization Code flow, that usually means logging into a web app that calls the API you are trying to authenticate into, and then consenting on the consent page. See https://dev.fitbit.com/docs/oauth2/#authorization-page for an example (I implemented OAuth 2 for Fitbit :)). You'll need to use an automated web browser like Selenium to click the consent button. Then you can capture the code in the response from /authorize and send the code to the access token endpoint.
Related
A Django site acts as an oauth2 provider. A setup for an app tomcat_app looks like:
Whenever somebody tries to login into tomcat_app a user will get redirected to Django. If the user can provide valid credentials they will get redirected to tomcat_app. So far so good. Tomcat_app further offers a REST API which is aware of the oauth2 workflow. If the reqeust supplies a valid token requests will get accepted.
The knot in my head: A third server should be granted to use the tomcat_app rest api as well. Is it possible to
setup a new user in django externalapp_user/externalapp_password
obtaining a key for tomcat_app by sending the new users credentials to django
Where I'm puzzled is, is how to correctly send the credentials and how to deal with the redirect url. I'm looking for something similar to client type: public and Authorization grant type: Resource ownder password-based
curl -X POST -d "grant_type=password&username=admin&password=admin" http://client:secret#localhost/o/token/
What I understand from the django-oauth-toolkit documentation is that: If you want to use 'Resource owner password-based' Authorization grant type you need to have the user registered on your tomcat_app.
But if you don't want to have the user registered on your app and still provide him with the api endpoint, It is better to use 'Client credentials' Authorization grant type. This will give the third party app the ability to access your api endpoints after they login their users.
You can check out the documentation for better understanding the 'Client credential' flow.
How can I validate a username/password against Azure AD without showing a UI? I have an autonomous processes running (think Windows Service or scheduled task) where the username and password are stored in a configuration table.
Since there is no "user at the wheel" so to speak, we can't use the normal method that shows the Azure login page (https://login.microsoftonline.com/{tenantId}).
1. Just make it work, no changes approach (Not Recommended)
You can try to get a token using Resource Owner Password Credentials Grant. (ROPC might be the least secure among all the different grants supported and brings potential attack risks. Also note that ROPC doesn't work with MFA and has issues with federated authentication users or may not work in those cases at all)
I don't think there is any method/endpoint available to specifically validate the username/password, but the workaround is if either username or password is incorrect, you will get an exception from the token endpoint when using ROPC, otherwise you get back a valid token which means credentials are good.
You can read about how to get a token using ROPC here:
Resource Owner Password Credentials Grant in Azure AD OAuth
2. Suggested Approach, some changes required (Recommended)
This might feel a little inconvenient at beginning, but it will be well worth the effort from a security standpoint. Note that this approach as well as the first one will meet your requirement of not going through normal login page as well.
Since there is no "user at the wheel" so to speak, we can't use the
normal method that shows the Azure login page
(https://login.microsoftonline.com/{tenantId}).
As you mention that the autonomous process is like a Windows Service or Scheduled task, from Azure AD and OAuth 2.0 perspective your process looks like a Daemon service. So instead of using a username/password credentials directly from configuration, which violates security best practices, you should be looking at using Client Credentials Grant. It's strongly advised NOT to collect/manage/store end user credentials (or create old world Service Accounts) directly in your applications.
You can read about it in detail here: OAuth 2.0 Client Credentials Grant with Azure AD.
Also visit this documentation for all Azure AD app types and scenarios, specifically those listed for Daemon apps. Link
To put it very briefly, your process gets represented by a registered application in Azure AD and for credentials part you can use:
a. Client ID + Client Secret Key (provided by Azure AD specifically for your application. you can generate more than one secret keys for different purposes with different expiration etc.). Sample C# code with Client Secret
b. Client ID + Certificate (pass a JWT that you need to create and sign with the certificate you registered as credentials for your application). Sample C# code with Certificate
I am trying to implement WEB API 2 (for Single Page App, not as part of Visual Studio project) OAuth2.0 protocol. As per Which OAuth 2.0 flow should I use, using refresh tokens is not an option. However, I am not sure I understand Implicit Grant flow with eventual Silent Authentication.
Does Implicit Flow mean only issuing normal access tokens? In that case, how do we allow user to stay logged in for long time? How should Silent Authentication endpoint look like, what should it receive and return to client? Is using refresh token really an issue - most of people have their usernames / passwords saved in browser?
Does Implicit Flow mean only issuing normal access tokens? Yes.
In that case, how do we allow user to stay logged in for long time? You can set timeout using "expires_in" parameter.
Refer for Complete Detail here: https://oauth2.thephpleague.com/authorization-server/implicit-grant/
How should Silent Authentication endpoint look like, what should it receive and return to client? Upon authentication of the user during login, the server sends & set the authentication key in the session/browser. So, during every page call, only authentication key is send to server. You shall find many examples of implementation online.
Is using refresh token really an issue - most of people have their usernames / passwords saved in browser? No, it's not an issue. If token expires, you can easily reissue token after authentication. Password & username is not saved in the browser. Only authentication key is stored.
Reading this question, #Pinpoint's answer and the further discussion on comments, I'm well aware that natively we can't add an identity provider to our apps developed with ASP.NET 5. One possible replacement for the legacy OAuthAuthorizationServerMiddleware is then provided by the AspNet.Security.OpenIdConnect.Server as I've found in many places.
Now, there is one point that I'm still unsure about all this because I'm really not an expert in security, so my knowledge about OAuth is not very deep. My doubt is the following: is it possible to use an external identity provider when using OAuth to protect one RESTful API?
Notice that I'm not talking about adding social login to one website, I'm talking about using one external identity provider in one RESTful API.
My point is, this makes me a little confused yet, because I always thought this should be a concern of my app.
So my question here is: when using OAuth and ASP.NET 5, is it possible to use an external identity provider, other than implementing one? If it is possible, how this works in short? I mean, my app still needs to be able to manage the identities of users, in the sense that it needs to manage claims and so on.
In that case, if it is really possible, how the flow would be? The external identity provider should issue the tokens? But how my app would be able to verify those tokens and manage users identities?
EDIT: One of the reasons I feel unsure about that is that when we use the UseOAuthAuthentication extension method, we set up one callback path which is described as
The request path within the application's base path where the user-agent will be returned. The middleware will process this request when it arrives.
Now, if we are developing a site, then this really does make sense. The person goes there, click a button to login with a provider like Facebook. The user is redirected to Facebook's page and then after he logs in, he is redirected to some page of the site.
On the other hand, with a RESTful API this is meaningless. There is no notion of being redirected.
This makes it seems that the usage of external providers is only for sites and not for RESTful API's. This is the main point of my question.
My doubt is the following: is it possible to use an external identity provider when using OAuth to protect one RESTful API?
Yes, it's definitely possible. This is exactly what you do when you use Azure Active Directory to protect your API endpoints:
app.UseOAuthBearerAuthentication(options => {
options.AutomaticAuthenticate = true;
options.Authority = "https://login.windows.net/tushartest.onmicrosoft.com";
options.Audience = "https://TusharTest.onmicrosoft.com/TodoListService-ManualJwt";
});
The next legitimate question is: if you can use the tokens issued by AAD to protect your API, why couldn't you do the same thing with Facebook or Google tokens?
Unlike Facebook or Google, AAD issues completely standardized tokens named JWT tokens that the OAuth2 bearer middleware can "read" and "verify" to determine whether the token is still valid and was really issued for your API (i.e if the audience attached with the token corresponds to your API. You can control this value using the resource parameter when making your authorization request).
You can't do something similar with FB or Google tokens, since they are totally opaque. Actually, it's not really surprising since these tokens have only one objective: allowing you to query FB or Google APIs, not your own ones (these social providers don't allow to set the audience of the access token).
Since you can't read the token yourself, the only option is to ask FB or Google whether it is still valid to make sure your API doesn't accept invalid tokens. That's something you can (easily) do with Facebook as they offer a "token inspection endpoint" you can query for that: https://developers.facebook.com/docs/facebook-login/manually-build-a-login-flow (see the Inspecting access tokens chapter). This way, you can ensure the token is not expired and determine the user corresponding to the token.
Sadly, this approach has two downsides:
You have to make an extra HTTP call to the Facebook endpoint to validate the access token, which implies caching received tokens to avoid flooding Facebook with too many requests.
As the access token is not issued for your own API, you MUST absolutely ensure that the access token was issued to a client application you fully trust, or it will allow any third party developer to use his own FB/Google tokens with your API without having to request user's consent. This is - obviously - a major security concern.
You can find more information in the last part of this SO answer (it's for Katana and about Dropbox, but you should get the idea): OWIN/OAuth2 3rd party login: Authentication from Client App, Authorization from Web API
So my question here is: when using OAuth and ASP.NET 5, is it possible to use an external identity provider, other than implementing one? If it is possible, how this works in short? I mean, my app still needs to be able to manage the identities of users, in the sense that it needs to manage claims and so on.
In that case, if it is really possible, how the flow would be? The external identity provider should issue the tokens? But how my app would be able to verify those tokens and manage users identities?
To work around the limitations mentioned in the previous part, the best option is - as you've already figured out - to create your own authorization/authentication server. This way, your API doesn't (directly) accept FB or Google tokens but the tokens issued by your own server, that can possibly redirect your users to FB or Google for authentication.
This is exactly what this sample does: https://github.com/aspnet-contrib/AspNet.Security.OpenIdConnect.Server/tree/vNext/samples/Mvc
The user is invited by the client application (Mvc.Client) to authenticate with your authorization server (Mvc.Server) so he can get an access token to later query the API (also in Mvc.Server). For that, the user is redirected to your authorization server, which itself offers you to authenticate with Google or Twitter.
When this external authentication step is done, the user is redirected back to your authorization server (Mvc.Server), where he's asked to give his consent for the client app (Mvc.Client) to access his personal data.
When the consent is given, the user is redirected back to the client application with the access token you can use to query the API endpoint.
I'm using VS2013 and Web API 2 to create a self-hosted (using OWIN), RESTful service over SSL using token authentication. Although I'm not a novice developer, this is my first time looking at ASP.NET technologies, so please keep that in mind.
I've got everything more-or-less working except for the authentication and authorisation parts. I fully understand the difference of authenticating a user (who is this user?) and authorising an already authenticated user to access a resource (can this user access this particular resource?).
A very simple overview of my auth process is as follows (makes some assumptions for brevity):
An unknown client connects to the API, e.g. GET api/values.
The server responds with a 401 and this response header: "WWW-Authenticate: Token".
Upon seeing this, the unknown client knows to connect to a different API endpoint here: POST api/auth (routed to the Login function), supplying the username and password.
The server will try to figure out if this is a valid user and can accept or reject the user depending on the validity of the credentials.
(Rejected) The server returns an error status code (403?). End of process.
(Accepted) The server creates a random token (e.g. a GUID) and stores it against the user record. Then it sends the token to the client.
The now authenticated client reconnects to the API, GET api/values, and this time also supplies the token.
The user returns the resource data to the client.
...
The user can log out by connecting to the same API as he used to log in: POST api/auth (this time, his request will be routed to the Logout function). This will remove the token from the server and the client will also have to remove its own token.
As you can see, this is a relatively simple process, but I can't find any concrete and simple examples to understand how best to achieve this with a self-hosted Web API 2.
I don't need to register users or do any password/roles management, etc. and there is no external authentication. All valid users have the same rights to access the resources and they're already created in the system by a separate process over which I have no control (I can only read their credentials for validation). Most examples I found are talking about security frameworks that I don't need, so I've ruled out using any of the following: Basic Authentication, Windows Authentication, Forms Authentication, Individual Accounts, ASP.NET Membership/Identity, OAuth, Thinktecture or any other security framework.
I've read articles about authenticating in a message handler and others about authentication in a custom Authorize attribute filter, while others even suggest I should use the new (in Web API 2) IAuthenticateFilter attribute. This is very confusing. Can you please advise on a very simple way to achieve my auth objectives? Any specific code examples will be greatly appreciated, even if they're just skeleton implementation or pseudocode. I just need some ideas to get me started.
After a lot of googling, I found this article on CodeProject: http://www.codeproject.com/Articles/630986/Cross-Platform-Authentication-With-ASP-NET-Web-API. While this is not Web API 2 or self-hosted, it has given me a number of ideas on how to proceed.
Someone also posted a comment to that CodeProject article referencing a NuGet package that may interest anyone looking for something similar: https://www.nuget.org/packages/WebApiTokenAuth. In my case, it is a bit much.
Finally, in addition to the authentication options mentioned in the question, there's also the option to write an OWIN middleware to do authentication if self-hosting using OWIN (as per the official MS recommendation). However, I plan to implement this particular form of token authentication with a message handler, as there's more support for this method available than for writing OWIN middleware.