Google storage item with CORS and cookie-based authentication - cookies

My reading of this documentation is that if I wanted to make
an in-browser XMLHttpRequest on behalf of a logged-in user, I would need to use a URL of the form:
https://storage.cloud.google.com/BUCKET/OBJECT
Because those URLs respect cookie-based authentication.
However, my testing seems to indicate that the CORS headers set for the bucket are not sent along with the response from URLs of that form (but they are from URLs of the form storage.googleapis.com/BUCKET/OBJECT).
Is this true? Is there no way to get both cookie-based authentication, and CORS headers?

You are correct. Custom CORS policies are only fully supported via the "storage.googleapis.com" endpoint (including custom domain names with CNAME redirects to c.storage.googleapis.com), and that endpoint does not support cookies. There is not a good way to use both at once.
I would suggest avoiding cookie-based authentication if you can. OAuth 2 is a good alternative and may provide additional benefits, depending on what you are trying to do.

Related

Does Akamai NetStorage has a presigned URL feature

Currently, Akamai has many upload mechanisms like FTP, RFTP, NetStorage Api and Aspera.
I would like to know whether Akamai NetStorage has a presigned URL feature-- A presigned URL is a URL that you can provide to your users to grant temporary access to a specific Akamai’s directory, Using the URL, a user can either READ the object or WRITE an Object (or update an existing object)
Thanks,
As far as I know NetStorage doesn't have that functionality out of the box, however you could implement that using Edge logic. Basically you create an Akamai Edge Configuration that uses NetStorage as origin and enforces Edge URL authentication.
You can generate the tokens using the App of your choice (i.e. AWS or Azure), and then have the token validated on the Akamai Edge. Feel free to contact Akamai Technical support if you need more guidance.
It depends on your architecture. Netstorage is Read/Writeable - subject to correct authentication headers accompanying your "presigned" URL. Such access to NetStorage is NOT scaleable. So if you just want to give a URL to many users, then you simply need a property configured in Akamai to do what you want.

Conflicts Between Caching and SignedURL(making content private)

I am making an app which includes a messaging feature. Through the messaging feature, users can send photos to others users. These photos should be completely private.
At first, I thought of S3's signedURL feature. But then I realized that I cannot make caching work which is done by my CDN provider and my client side because caching is done based on URLs.
So I moved on to CloudFront's signed cookie. It seemed promising at first, but I found another problem. Users who got signed cookies can access to any content in the allowed scope. But I should not allow to show photos that were sent in other chat rooms. Users who have signed cookies should not be able to access to photo urls that were not shared in their rooms. So I cannot use signed cookies.
I moved on to CloudFlare and found a post that they were allowed to use special cache keys instead of url based caching. (https://blog.bigbinary.com/2019/01/29/how-to-cache-all-files-using-cloudflare-worker-along-with-hmac-authentication.html) I do not know how much the Enterprise Plan is, but Business Plan which is one level below is $200/month.
The business plan allows CloudFlare users to use token authentication. (https://blog.cloudflare.com/token-authentication-for-cached-private-content-and-apis/) (https://support.cloudflare.com/hc/en-us/articles/115001376488-How-to-setup-Token-Authentication-) I might be able to utilize this token authentication by making my images including tokens like this:
<Image source={{
uri: 'https:image_url.jpeg',
method: 'GET',
headers: {
Authorization: token
},
}}
style={{width: width, height: height}}
/>
Another thing I could do is getting signed URLs from CloudFront, not from a S3 level. In that way, I can make my CDN(CloudFront, in this case) to properly cache my S3 images and then make unique URLs per photo. But I still have to deal with client side caching as URLs clients see are always different. I have to save URLs in Localstorage as this(https://stackoverflow.com/a/37817503) answer suggested. Or I can use a React Native caching library. However, I will deploy this app on the web as well as mobile environment, so I am not sure if it will be a viable option for me to use such caching libraries.
To sum up, signed URLs cause two-level problems. It does not work with CDN caching. It does not work with client caching. I should use CloudFront's signed URLs and deal with client side caching(which is not ideal) Or I should use CloudFlare's token method. Bandwidth is free for CloudFlare, though Business Plan costs $200. So will it be worth it if I assume my app scales well?
What discourages me from using CloudFlare is it is not well documented. I have to deal with workers in CloudFlare, but the only document I found about how to use signed URL in the CDN level is this (https://developers.cloudflare.com/workers/about/tips/signing-requests/#verifying-signed-requests) And the only one I found about how to access to S3 private bucket from CloudFlare is this (https://help.backblaze.com/hc/en-us/articles/360010017893-How-to-allow-Cloudflare-to-fetch-content-from-a-Backblaze-B2-private-bucket)
Is CloudFlare with token verification method the right way to go for me? Is there any other method I can try out?

Django rest framework and cross origin requests

I try to do some request from a javascript client to rest api build with Django rest framework.
All GET request to /api/test are public, then no session or token or watever are needed.
All POST to api/test are private and user have to use oauth2
According to the documentation, I have to manage cross origin request with django-core-headers. After installing this module to my django, I've set
CORS_ORIGIN_ALLOW_ALL to True but:
1) is it a good practice ?
2) is there a good solution to allow cross origin request only on some points ?
Thanks
With django-core-headers you can restrict CORS origins with CORS_ORIGIN_WHITELIST and CORS_ORIGIN_REGEX_WHITELIST. If you don't need to allow arbitrary origins, then set those; otherwise, you're good.
You could, if you wanted to, write a decorator to check origin in your views to see if it matches a desired origin (perhaps something set on whatever model is tracking which users are authorized for POST requests?). But if you're allowing GET requests from any arbitrary origin, and don't care where POST requests come from as long as they are authorized, then you're in the clear--after all, how can you restrict origin if you don't know where clients might make requests from?

Standard -server to server- and -browser to server- authentication method

I have server with some resources; until now all these resources were requested through a browser by a human user, and the authentication was made with an username/password method, that generates a cookie with a token (to have the session open for some time).
Right now the system requires that other servers make GET requests to this resource server but they have to authenticate to get them. We have been using a list of authorized IPs but having two authentication methods makes the code more complex.
My questions are:
Is there any standard method or pattern to authenticate human users and servers using the same code?
If there is not, are the methods I'm using now the right ones or is there a better / more standard way to accomplish what I need?
Thanks in advance for any suggestion.
I have used a combination of basic authentication and cookies in my web services before. In basic authentication you pass the user name/password encoded in the HTTP header where it looks something like this.
Authorization: Basic QWxhZGluOnNlc2FtIG9wZW4=
The string after the word "Basic" is the encoded user name and password that is separated by a colon. The REST API can grab this information from the HTTP header and perform authentication and authorization. If authentication fails I return an HTTP Unauthorized error and if they are authenticated but are not authorized I return an HTTP Forbidden error to distinguish between failure to authentication versus authorization. If it is a web client and the person is authenticated then I pass the following in the HTTP header with a request.
Authorization: Cookie
This tells the web service to get the cookie from the HTTP request and use it for authorization instead of doing the authentication process over again.
This will allow clients that are not web browsers to use the same techniques. The client can always use basic authentication for every request, or they can use basic authentication on the initial request and maintain cookies thereafter. This technique also works well for Single Page Applications (SPAs) where you do not have a separate login page.
Note: Encoding the user name and password is not good enough security; you still want to use HTTPS/SSL to secure the communications channel.

How do I implement login in a RESTful web service?

I am building a web application with a services layer. The services layer is going to be built using a RESTful design. The thinking is that some time in the future we may build other applications (iPhone, Android, etc.) that use the same services layer as the web application. My question is this - how do I implement login? I think I am having trouble moving from a more traditional verb based design to a resource based design. If I was building this with SOAP I would probably have a method called Login. In REST I should have a resource. I am having difficulty understanding how I should construct my URI for a login. Should it be something like this:
http://myservice/{username}?p={password}
EDIT: The front end web application uses the traditional ASP.NET framework for authentication. However at some point in the authentication process I need to validate the supplied credentials. In a traditional web application I would do a database lookup. But in this scenario I am calling a service instead of doing a database lookup. So I need something in the service that will validate the supplied credentials. And in addition to validating the supplied credentials I probably also need some sort of information about the user after they have successfully authenticated - things like their full name, their ID, etc. I hope this makes the question clearer.
Or am I not thinking about this the right way? I feel like I am having difficulty describing my question correctly.
Corey
As S.Lott pointed out already, we have a two folded things here: Login and authentication
Authentication is out-of-scope here, as this is widely discussed and there is common agreement. However, what do we actually need for a client successfully authenticate itself against a RESTful web service? Right, some kind of token, let's call it access-token.
Client) So, all I need is an access-token, but how to get such RESTfully?
Server) Why not simply creating it?
Client) How comes?
Server) For me an access-token is nothing else than a resource. Thus, I'll create one for you in exchange for your username and password.
Thus, the server could offer the resource URL "/accesstokens", for POSTing the username and password to, returning the link to the newly created resource "/accesstokens/{accesstoken}".
Alternatively, you return a document containing the access-token and a href with the resource's link:
<access-token
id="{access token id goes here; e.g. GUID}"
href="/accesstokens/{id}"
/>
Most probably, you don't actually create the access-token as a subresource and thus, won't include its href in the response.
However, if you do so, the client could generate the link on its behalf or not? No!
Remember, truly RESTful web services link resources together in a way that the client can navigate itself without the need for generating any resource links.
The final question you probably have is if you should POST the username and password as a HTML form or as a document, e.g. XML or JSON - it depends... :-)
You don't "login". You "authenticate". World of difference.
You have lots of authentication alternatives.
HTTP Basic, Digest, NTLM and AWS S3 Authentication
HTTP Basic and Digest authentication. This uses the HTTP_AUTHORIZATION header. This is very nice, very simple. But can lead to a lot of traffic.
Username/Signature authentication. Sometimes called "ID and KEY" authentication. This can use a query string.
?username=this&signature=some-big-hex-digest
This is what places like Amazon use. The username is the "id". The "key" is a digest, similar to the one used for HTTP Digest authentication. Both sides have to agree on the digest to proceed.
Some kind of cookie-based authentication. OpenAM, for example, can be configured as an agent to authenticate and provide a cookie that your RESTful web server can then use. The client would authenticate first, and then provide the cookie with each RESTful request.
Great question, well posed. I really like Patrick's answer. I use something like
-/users/{username}/loginsession
With POST and GET being handled. So I post a new login session with credentials and I can then view the current session as a resource via the GET.
The resource is a login session, and that may have an access token or auth code, expiry, etc.
Oddly enough, my MVC caller must itself present a key/bearer token via a header to prove that it has the right to try and create new login sessions since the MVC site is a client of the API.
Edit
I think some other answers and comments here are solving the issue with an out-of-band shared secret and just authenticating with a header. That's fine in many situations or for service-to-service calls.
The other solution is to flow a token, OAuth or JWT or otherwise, which means the "login" has already taken place by another process, probably a normal login UI in a browser which is based around a form POST.
My answer is for the service that sits behind that UI, assuming you want login and auth and user management placed in a REST service and not in the site MVC code. It IS the user login service.
It also allows other services to "login" and get an expiring token, instead of using a pre-shared key, as well as test scripts in a CLI or Postman.
Since quite a bit has changed since 2011...
If you're open to using a 3rd party tool, and slightly deviating from REST slightly for the web UI, consider http://shiro.apache.org.
Shiro basically gives you a servlet filter purposed for authentication as well as authorization. You can utilize all of the login methods listed by #S.Lott, including a simple form based authentication.
Filter the rest URLs that require authentication, and Shiro will do the rest.
I'm currently using this in my own project and it has worked pretty well for me thus far.
Here's something else people may be interested in.
https://github.com/PE-INTERNATIONAL/shiro-jersey#readme
The first thing to understand about REST is that its a Token based resource access.Unlike traditional ways, access is granted based on token validation. In simple words if you have right token, you can access resources.Now there is lot of whole other stuff for token creation and manipulation.
For your first question, you can design a Restfull API. Credentials(Username and password) will be passed to your service layer.Service layer then validates these credentials and grant a token.Credentials can be either simple username/password or can be SSL certificates. SSL certificates uses the OAUTH protocol and are more secure.
You can design your URI like this-
URI for token request-> http://myservice/some-directory/token?
(You can pass Credentilals in this URI for Token)
To use this token for resource access you can add this [Authorization:Bearer (token)] to your http header.
This token can be utilized by the customer to access different component of your service layer. You can also change the expiry period of this token to prevent misuse.
For your second question one thing you can do is that you grant different token to access different resource components of your service layer. For this you can specify resource parameter in your token, and grand permission based on this field.
You can also follow these links for more information-
http://www.codeproject.com/Articles/687647/Detailed-Tutorial-for-Building-ASP-NET-WebAPI-REST
http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api
I have faced the same problem before. Login does not translate nicely to resource based design.
The way I usually handle it is by having Login resource and passing username and password on the parameter string, basically doing
GET on http://myservice/login?u={username}&p={password}
The response is some kind of session or auth string that can then be passed to other APIs for validation.
An alternative to doing GET on the login resource is doing a POST, REST purists will probably not like me now :), and passing in the creds in the body. The response would be the same.