I have a client-side angular-js application. And I have a server-side nodejs API. The client-side and the server-side application are located on different domains. The client-side use API for getting or posting some data. Also the client-side needs to get images from the server-side and show them in a browser.
I use passport nodejs module for the authentication. I don't know which authentication strategy is better for me. I think that there are two types of authentication strategies: token-based and cookie-based. And I think that both types useless in my case:
If I use token-based strategies, then I should send Authentication header with a token in each request to the API. I can send headers in AJAX requests, but if I want to show an image that is located on the server-side I have a problem. Because a browser will not send headers in <img> tag.
If I use cookies, then I don't have the problem with images. But I have problems with AJAX requests. Because the session cookie is stored on the server-side application's domain. And if I send AJAX requests from the client-side domain, then I should send cookies with each request. I use XmlHttpRequest for AJAX and I should use withCredentials option for sending cookies. But in crossdomain requests browsers will send a preflight (OPTION) request before each AJAX request. And browsers will not send cookies with OPTION request. This is a problem for me because the server-side API could not make a correct response on an OPTION request if it will be not authorized.
What is the adopted solution?
It is important to understand the difference between web applications and web services. A web application serves markup, JavaScript, CSS and image files and often uses cookie based authentication (but can use any other implicit authentication mechanism). Any request the browser makes is automatically authenticated.
Web services on the other hand often use bearer token authentication. When a client in a browser, fat client or on a mobile device communicates with the API, it sends along a token in the Authorization header of the HTTP request. The header has to be explicitly attached to the request in the JavaScript or native code executing the HTTP request.
In Single Page Applications (SPA), the web application is missing and the markup, JavaScript, CSS and images are served from the browser without authentication. Only the requests to the web services are authenticated, typically using a JWT token.
In your case, if you want only authorized users to be able to download images, and other files, you should consider building a web application. Use a security protocol like or OpenID Connect to authenticate your users. Choose an authorization server that supports both OpenID Connect for your web application and OAuth2 for your web service.
Related
I am wondering, if JWT should be attached to the header of my request manually, how can I use JWT to authenticate the users of my ASP.Net Core website?
In other words, how can I tell my browser to attach the token in the header when sending the request to my server? Let us say the user of my website got this token from one of my website's API.
Or is JWT usable only for WebAPI (where I can manually build the request)?
There are different ways to use JWT tokens. Since JWT is just a token format, it does imply the method used for authentication.
However, JWTs are mainly used for Bearer authentication scheme, which requires adding a custom header to each request. Single page applications (SPAs) that create requests in JavaScript on the client to access API endpoints can do that which is why Bearer+JWT is used a lot in SPAs. SPAs also benefit from the embedded JSON format since they can read expiration dates and other information (claims embedded in the token, ID token contents obtained via OpenID Connect etc.).
For "traditional" server-rendered views and links, using JWTs is hard since they'd have to be set as cookie or made part of the URL (practically impossible because of URL length restrictions). ASP.NET Core 2.0 does not contain any JWT-based cookie logic but it is possible to create a custom implementation using JWTs as cookies. See this GitHub project and related blog post for a sample implementation. Note that the only benefit of using JWTs in cookie authentication is that the server doesn't have to persist cookie information and share cookies across multiple instances.
To sum up the current state:
Prefer default cookie authentication when you use server-side rendering and links to avoid creating custom cookie implementations.
Prefer JWT bearer authentication if you have single page applications (SPAs) apps that build requests in javascript/typescript on the client.
My web service expects both browser and non-browser clients. And I use token based authentication to make the service stateless.
I store the token as cookies because I want when some Ajax calls initiated from the web page, the token is sent along automatically by the browser.
But for a non-browser client, how to handle cookie? Do I just manage the cookie as a plain HTTP header?
The ideal way to do this on a non-browser client is to use something like the OAuth2 protocol. This protocol was designed to securely handle stuff like this for both browser AND non-browser clients.
Here's how it works:
Your service exposes an OAuth2 endpoint, typically /oauth/token.
Your client sends a form-encoded POST request to /oauth/token, specifying what 'type' of OAuth2 the client is using. In the case of a non-browser client, you'd most likely supply grant_type=password in the body of your POST request.
You also include your username/password to authenticate yourself.
What your client will then get BACK, is an Access Token / Refresh Token that should be securely stored on your client.
If your client is a mobile device like iOS, you'd store the Access / Refresh Tokens in the iOS keychain -- if you're on Android, you'd store those tokens in Shared Preferences. Either way -- these are 'secure' storage locations meant for holding confidential information like tokens.
Then, when you need to use those tokens to authenticate against your service, you can simply POST to your API with that token, and bam, you will be authenticated.
This is the ideal way to handle token stuff in most situations. I'm the author of an authentication library in Node called express-stormpath, and this is how I do it as well.
I am creating a mobile application which will talk to my REST Web Services, for login, GET, POST, DELETE and logout. I have been trying to figure out how to secure these REST Web Services using Keycloak. I do not want any In Browser Login on the mobile application, so I was inclined towards Direct Grant API and Admin REST API for authentication and token validations. But, now after looking at the available options on Keycloak, every request from the mobile app must be intercepted, and then make a REST call to the Keycloak module for validating the token and then return a response back to the mobile app.
Is there a better way in doing this? Some inbuilt function calls to check the token validity instead of making an HTTP call for every request from the mobile app? I think this is a huge overhead.
My server is on JBOSS. Spring, Resteasy and Keycloak-services are being used to figure out a solution for this problem.
I have a web service built with WebAPI that accepts JSON requests and responds accordingly. The core architecture is built but there isn't any authentication/authorization.
After a lot of googling and poking around sample projects, I'm not sure where to start. I've found a ton of material from 2008 and 2009 but not a whole lot of recent guides/workflows for WebAPI / single page apps. I think the workflow should be as follows:
Check to see if the user is logged in: How can this be done with javascript? Do I send a cookie to my webAPI? If so, do I send that cookie as a parameter in the body of the request?
Let the user log in / register: How is this data encrypted/decrypted? Surely I can't be sending passwords over the wire... is this where SSL comes in?
Provide them with access to what they have rights to access: I think I got this - I can just authorize in the controllers on a per-request basis.
Any info would be awesome.
Basically you need a token based authentication or authorization.
If you are referring to the ASP.NET WebAPI, the following project will be a great place to start:
http://thinktecture.github.com/Thinktecture.IdentityModel.45/
Even if you are not using ASP.NET WebAPI, the following video is a great introduction on how to provide authentication/authorization on RESTful web services:
http://vimeo.com/43603474
To answer some of your questions:
Check to see if the user is logged in: How can this be done with javascript? Do I send a cookie to my webAPI? If so, do I send that cookie as a parameter in the body of the request?
You can use a cookie but I normally use the header in order to avoid common XSRF attacks. Cookies are automatically included whenever a http request is sent from the browser.
is this where SSL comes in?
Yes. If you are going to go ahead with the token based approach, you can use a separate server (Identity Server) to do the authentication for you.
JavaScript clients are unique. Do you have the Web API and the page serving up JavaScript in the same domain? If not, you have same origin policy restrictions. If you have the same Web application hosting the web pages and Web API, you can use forms Authn. In that case, you don't need to send the cookie containing the authentication ticket yourself from JavaScript. Browsers do that for you and that is the cause of XSRF problem. You have to be careful about JavaScript sending credentials that the end user is not supposed to know. If JavaScript knows something, any intelligent end user can get to that knowledge. OAuth 2.0 implicit grant could be a good choice. The end user enters the credentials (password) in the authorization server which issues an access token. JavaScript gets the token and presents it to the web API but it will never have access to the credentials.
According to https://dev.twitter.com/docs/api/1/post/oauth/request_token, it is strongly recommended you use HTTPS for all OAuth authorization steps. However, I found out the callback url is not following this suggestion. Is there a difference if a https callback url is given vs a http callback url is given?
For example,
Request URL:
POST https://api.twitter.com/oauth/request_token
Authorization Header:
oauth_callback="http%3A%2F%2Fmyapp.com%3A3005%2Ftwitter%2Fprocess_callback",
The callback URL just needs to in a url format, the Oauth spec does not mandate that it is https.
Certain Oauth providers (like SalesForce) do force the use of https.
Most service providers however just force you to register you callback url so that the service provider can verify that the correct callback url is provided during an oauth dance using your consumer key / secret.
Also, mobile apps in Android can create special protocol handlers, allowing callback handlers like "linkedin://callback" to be defined (to let the Android app handle linkedin oauth callbacks).
In that scenario it wouldn't make sense to force https, as it would force mobile apps to off-load their oauth dance to a remote server, where in some cases its perfectly acceptable to do it in the app itself.
Also keep in mind that whe the access token is compromised, people wishing to make secured api calls also need access to the consumer key / consumer secret.