Temporary authentication via query string - authentication

My goal is to be able to generate a special URL that would allow someone to view a normally "protected" view temporarily. In fact, if they leave the page, any temporary authentication that was granted should be taken away.
Basically the problem is that I have content on my website that I NORMALLY want to be protected by requiring a login. However, I'd like to be able to give temporary access to a specific asset and not require a login.
Should I somehow use a URL with a query string that automatically authenticates the user? Or should I instead generate a separate page with that asset that does not require authentication at all?
edit: I forgot to mention that the generated link should be accessable for more than one person. In other words, it can't limit by the number of times accessed, but rather a time period or until we manually force it to expire.

You can create a database table like tokens, where you store unique access tokens which are valid only for 1 single request. In your action, this token could be a URL parameter. If no token is present in URL or if the token was not found in the DB table, access is denied. If a token was found, you delete it from DB and perform the action.
Now whenever you want to give someone this kind of one-off access, you create such a token and store it to DB. The token could be a random MD5 hash, that you generate e.g. through md5(mt_rand().mt_rand()). Then you can create a URL with that token as parameter and hand it out to the user.
You can also enhance the system and add an expiration time to your tokens table. Then you'd only grant access if the expiration time is in the future.

vyce: "It should first be for a rendered view that also contains PDF files."
If you have PDF files (or any other files) accessible under your webroot, anyone can access them at any time. So even if you will only serve a view to your user once, he/she could still get to the PDF file if they have kept the PDF's URL. The user can also share that URL with others.
This problem can be resolved by:
Storing the PDF file under the document root (or in another location that is made inaccessible with .htaccess)
Once you have determined that your user is allowed a one-time peek at the PDF, you serve it as described here

Related

How is the access_type=online oauth mode (no refresh token) supposed to work?

This question is has a lot in common to the previous question Google OAuth: can't get refresh token with authorization code (and I won't be offended if it's considered a duplicate) but there are some differences: that question uses the Javascript and PHP libraries, and I'm using neither of those. That question wants to know how to get a refresh token, and I want to know if I should want a refresh token, or how the mode with no refresh tokens is intended to work.
I'm following this guide:
https://developers.google.com/identity/protocols/OAuth2WebServer
The goal is to allow users to upload files from Google Drive to my web application.
I'm not using one of Google's favored programming languages, so I don't have a library abstracting away all the interaction with Google. I need to know what the HTTP requests should actually should look like.
One of the parameters in the authorization request is access_type. The description says
Set the value to offline if your application needs to refresh access tokens when the user is not present at the browser.
I won't need to do that (I'll only want to retrieve a file on my server immediately after the user selects it) so in the spirit of not asking for more privileges than you really need, I used access_type=online. This gives me an access token and no refresh token. I've successfully used the access token to make some requests to Google Drive.
The user comes back the next day and tries to upload another file. While processing this request from the user, I make a request to Google Drive. The access token is expired, so I get a 401. What's supposed to happen next?
My guess is I should pretend this is a completely new user and send them through the full authorization process again. That would mean I have to abort whatever the user was trying to do, redirect them to https://accounts.google.com/o/oauth2/auth with all the parameters (scope, client_id, etc.) and embed enough information in the state parameter that I can resume the original request when the user gets back from their detour.
This seems rather difficult (in particular the part about saving and resuming the state of my application at some arbitrary point). It's a big enough obstacle that it should be explained somewhere. But the description of the access_type parameter didn't say anything about needing to insert authorization redirects everywhere. It just said the user must be "present".
You are using the right implementation. You don't need offline access if you aren't going to make requests when the user is not using the application. The thing is that access tokens expire in 1 hour. So you need to generate new access tokens if a user leaves the application and come back later.
If users have authorized your application, calling this URL with your configuration should return a new valid access token:
https://accounts.google.com/o/oauth2/v2/auth?
scope=scopes&
include_granted_scopes=true&
state=state_parameter_passthrough_value&
redirect_uri=http://oauth2.example.com/callback&
response_type=token&
client_id=client_id

Claims-based auth and circles of users

Let's think of a simple REST-based web service to store and retrieve JSON objects. Without any authentication, every user can access any data.
Now let's add usage of JWTs to authenticate users. Of course, since we are not doing authorization, still every user can access anything, but at least now we know who accesses what.
Next step: When storing an object, save the user's sub claim with the object, and verify that the user's sub claim matches the one of the requested object, and if so, deliver it. Now we have authorization on a per-user basis. So far, so easy.
Now let's add the possibility to let users share objects with other users. For the sake of simplicity, say, we want to have predefined groups (i.e., roles) and we want to let the user choose which group (role) has access to the objects they create. This is still easy, as you have a predefined list of groups, so you can let the user choose one or more, and attach them to the object. Additionally, the identity provider needs to be configured in a way that it put a groups claim into every user's token, so we can match them. As we can already see from the length of this paragraph, things become more complex.
Question 1: Am I right so far, that handling "static" groups this way it the way to go?
Now, let's give the users the opportunity to create groups on their own. This is still not complicated, but how do we make the identity provider use the dynamically created groups? For sure we do not want to make an administrator update the identity provider's configuration every day ;-).
Question 2: How do we handle dynamically created groups?
Now, finally, let's forget about groups, and let's say, that we want to allow the users to be able to simply share their objects with other users. This should be configurable for every object individually. How do we do this? Do we save a list of users on the object? If so, what exactly do we save? The sub claim? If so, how does the owner user know the appropriate values? Or ...?
And: Supposed the users want to put their friends dynamically into dynamically generated circles, how would we do that?
Question 3: How do tokens and dynamically created groups with dynamically assigned users work with each other?
In my opinion the tokens should only include identity-information(-claims) you'll need to identify the user on your ressource server or that wont change when refreshing, since you wouldn't want your user (or your app in place) to have to refresh his access tokens each and every time his permissions change (since access tokens grant access for a specific amount of time you wouldn't want your user to have access to certain ressources that he's lost the access rights to since his last token refresh by not refreshing the token and simply using the old one either). The more security related information you append to your token, the more vulnerability you may add to your system (depending on your token lifetime).
Stating so, I would (and always do) identify the users roles or groups by his user-id (which is included in the jwt-token) on the ressource server. To achieve this, I always attach the users identity-information to the current request on my ressource server and attach "dynamic"-claims like the users role or group to the identity.
By adding only the identity information I need to identify the user and the user's rights on my ressource server, I tend to use my identity providers across multiple applications without handling application scope on the identity provider, so I can use the exact same access token for multiple independent ressource servers.

Revoke Shared Access Signatures after initial access in Azure Storage

I would like to essentially allow for one-time access to certain blob resources, requiring the user to check back with my server to get a new shared access signature before being able to access the resource again.
I have an implementation of this that I currently use, but I'm curious if there's something more ideal out there (particularly something already implemented in the Azure API that I missed).
Right now, a user can request the resource from the server. It validates their access to it, creates a unique hash in a database, directs the user to a link with that hash and the user loads the page. Once the page loads and they've completely downloaded the resource, I immediately invalidate the hash value in the database so it cannot be used again.
I know that Shared Access Signatures allow for time-based expiration, but do they allow for any sort of retrieval-count-based expiration, in that the user can completely download the resource and then the SAS invalidate itself? Thanks!
One time use is not supported by SAS tokens. If you get a chance it would be great if you could add this request to our Azure Storage User Voice Backlog. I would also encourage other people with the same requirement to vote on that as wel.
Thanks
Jason

How can I make a CouchDB database readable for public while having set require_valid_user to true?

My goal is to be able to read one database without having to authenticate the user, authentication for editing this database should be required. All other databases should only be read/writeable for valid users. And I don't want having to set it for every database I create in the future, authentication required for read/write required should be the default.
I thought I could do this by setting require_valid_user to true, but now CouchDB always asks for username and password, so I need a way to exclude one database. This database should be readable for public and writeable for valid users then.
I get around this problem by authenticating all users through one single database (i.e. /login). That database is public, and contains a design document with an HTML file as an attachment. The user is served this file, fills out their credentials on a form, and I use jQuery.couch.js to authenticate and store a cookie in their browser. Once they've got a valid login, I inspect the userCtx object to check their role, and redirect them to the appropriate database.
It's a hack, but until CouchDB is able to serve a login page instead of a JSON error message whenever you're not logged into a database, it's the only reliable method I've found.
Make sure to protect your public login database with a validate_doc_update key in the design document, so nobody but admins can overwrite anything in it.
Hope this helps.

Grails Spring Security forcing user to a specific screen after successful authentication

Here is the scenario. I have two objects Users (with username/password) and UserInfo with rest of the data related to user. The Users is an old table with thousands of records and UserInfo is fairly new. I want to get as much UserInfo as I can when the user first logs in.
I'd like to force user to a custom screen after first login and ask for the UserInfo data. Once I get the "required" data in the new screen, I dont show it till the user voluntarily wants to fill in the data under "Profile".
Since there are multiple entry points to the application, I dont want to update all the controllers to check for this.
Is there a way I can use a Spring Security filter or something which is executed on successful login? I had a look at ApplicationListener<AuthenticationSuccessEvent> but it doesnt solve the problem as if I copy paste the link in the browser, it lets me go ahead to the destination without asking for "extra information".
In a nutshell, I want a check after each login which, if fails, user is not allowed to enter the application. No matter how he tries to get in.
In your Config.groovy, configure Spring Security's defaultTargetUrl and tell it to always redirect there:
grails.plugins.springsecurity.successHandler.alwaysUseDefault = true
grails.plugins.springsecurity.successHandler.defaultTargetUrl = '/userInfo/edit'
In your UserInfoController's edit action, you can check that the required fields are present (userInfo.validate() perhaps?) and if they are, redirect to wherever you like, perhaps '/', otherwise render the edit info view.
You can adopt what #doelleri proposed and enhance the rule by those steps:
run a batch task to assign a temporary ROLE_DISABLED role to each user who does not provide supplemental information yet. If the user already had some roles, save them in some property.
setup your authorization rule as that users with ROLE_DISABLED role only allowed to access /userInfo/edit.
in /userInfo/edit, if the user has a ROLE_DISABLED role, render the information input view, and resume user's role after it successfully updated its information. Otherwise redirect to '/' or the path it requested.