How can I override Sitecore’s Media Handler to force user to redirect to login page if user is not authenticated - sitecore

I need a way to prevent access to files in media items if a user is not authenticated.
If a user is not authenticated he/she should be forced to redirect to the login page. If a user is authenticated then we should let the user to access the media item file, like we should handover the request to Sitecore.
Also help me on changing the configuration settings to override the existing MediaRequestHandler.

I would suggest using the OOTB Sitecore Security feature to grant or deny access to any item including media files.
This way you can restrict access to the specific assets only, not to ALL media files as in case with a bespoke media handler overriding the standard one, and you will not create any technical dependency on your custom code going forward. The latter is seen to be critical from the future website maintenance and Sitecore upgrade perspective.
To begin with, create a secure folder in the Media Library where you will be uploading the protected files and remove the READ permission from the anonymous user (typically it is extranet\anonymous). The full list of access rights can be found here. Expect all child assets to inherit the access permission from the parent folder. Now if you upload an asset into the restricted folder and try to request it in the frontend, you will get the "Access denied" message which is correct.
Next step is to create a new user role that will be allowed to view the restricted media files or use your existing one for the logged in users, assign the READ rights to this role, then assign this role
to the media folder and items you want to be accessible behind the login only.
Depending on your user experience on the website you can check whether the current context user can read a certain media item or not by calling item.Access.CanRead() method and then show or not a download/preview link for it or redirect to the login form.

Related

I need help in designing a database (and signup and login on base of their role )in which there are three user

I want make sign up and login on the base of their role there admin can add users and approved the request of other two user so that they can login.When user click on the sign up the user see sign up page accorading to their roll and same for login .
Django implements a pretty decent authentication framework inside it, so you already have things such as Users, Groups and Permissions to work on. All of those being managed easily by the admin page.
What you want to do is to assign a set of groups/permissions to a newly created user to determine its role and then build a frontend that manages the different kind of users in terms of templates. If you want an user to have itself validated before start using your page, refer to the is_active attribute of the User object.
Read for more information:
https://docs.djangoproject.com/en/2.2/topics/auth/default/#user-objects

How should a web application ensure security when serving confidential media files?

Question: Say a user uploads highly confidential information. This is placed in a third party storage server. This third party bucket uses different authentication systems to the web application. What is the best practice for ensuring only the user or an admin staff member can access the file url?
More Context: A Django web application is running on Google App Engine Flexible. Google Storage is used to serve static and media files through Django. The highly confidential information is passports, legal contracts etc.
Static files are served in a fairly insecure way. The /static/ bucket is public, and files are served through django's static files system. This works because
there is no confidential or user information in any of our static
files, only stock images, css and javascript, and
the files are uglified and minifed before production.
For media files however, we need user specific permissions, if user A uploads an image, then user A can view it, staff can view it, but user B & unauthenticated users cannot under any circumstances view it. This includes if they have the url.
My preferred system would be, that GCP storage could use the same django authentication server, and so when a browser requested ...google.storage..../media/user_1/verification/passport.png, we could check what permissions this user had, compare it against the uploaded user ID, and decide whether to show a 403 or the actual file.
What is the industry standard / best practice solution for this issue?
Do I make both buckets only accessible to the application, using a service account, and ensure internally that the links are only shared if the correct user is viewing the page? (anyone for static, and {user or staff} for media?)
My questions, specifically (regarding web application security):
Is it safe to serve static files from a publicly readable bucket?
Is it okay to assume that if my application requests a file url, that this is from an authenticated user?
Specifically with regards to Django & GCP Storage, if 2 is false (I believe it is) how do I ensure that files served from buckets are
only visible to users with the correct permissions?
Yes, it is. Public readable buckets are made for that. Things like, CSS, the logo of you company or some files that have no sensible data are safe to share.
Of course, do not use the same Public bucket to store private/public stuff. Public with Public, Private with Private.
Here is the problem. When you say "authenticated user", to whom you want that user to be authenticated to?
For example, if you authenticate your user using any Django methods, then the user will be authenticated to Django, but for Cloud Storage it will be an stranger. Also, even a user authorized on GCP may not be authorized to a bucket on Cloud Storage.
The important thing here is that the one that communicates back and forth with Cloud Storage is not the User, its Django. It could achieve this by using the python SDK of Cloud Storage, which takes the credentials of the service account that is being used on the instance to authenticate any request to Cloud Storage. So, the service account that is running the VM (because you are in Flexible) is the one that should be authorized to Cloud Storage.
You must first authorize the user on Django and then check if the User is able to access this file by other means(Like storing the name of the file he uploaded in a user_uploaded_files table).
Regarding your first question at the top of the post, Cloud Storage lets you create signed urls. This urls allow anyone on the internet to upload/download files from Cloud Storage by just holding the url. So you only need to authorize the user on Django to obtain the signed url and that's it. He does not need to be "authorized" on Cloud Storage(because the url already does it)
Taken from the docs linked before:
When should you use a signed URL?
In some scenarios, you might not
want to require your users to have a Google account in order to access
Cloud Storage, but you still want to control access using your
application-specific logic. The typical way to address this use case
is to provide a signed URL to a user, which gives the user read,
write, or delete access to that resource for a limited time. Anyone
who knows the URL can access the resource until the URL expires. You
specify the expiration time in the query string to be signed.
Following on from Nahuel Varela's answer:
My system now consists of 4 buckets:
static
media
static-staging
media-staging
Both the static buckets are public, and the media buckets are only accessible to the app engine service account created within the project.
(The settings are different for dev / test)
I'm using the django-storages[google]with #elnygrens modification. I modified this to remove the url method for Media (so that we create signed URLS) but keep it in for static (so that we access the public URL of the static files).
The authentication of each file access is done in Django, and if the user passes the test (is_staff or id matches file id), then they're given access to the file for a given amount of time (currently 1 hour), this access refreshes when the page loads etc.
Follow up question: What is the best practice for this time limit, I've heard people use anywhere from 15mins to 24 hours?

Any way to get "Employee Details" from Google API?

Is anyone aware of any Google API with the user scope (NOT the Admin API in the Directory SDK) that allows you to retrieve the custom employee attributes?
The G+ API seems to skip these
https://developers.google.com/+/web/api/rest/latest/people#resource
Our issue is that we don't want to grant access to the developer console, but rather do this PER-USER. I.E. a user logs into our app and we display to her the custom attributes for her G Suite account, but we do this as her (not as an approved API scope via the dev console).
Leaving this answer for anyone like me who finds this question.
The Directory API allows a user to query the custom attributes for their account even without any admin permissions at all.
https://developers.google.com/admin-sdk/directory/v1/reference/users/get
You need to ensure that projection is set to full and viewType is set to domain_public.
You may need to check the permissions for reading the custom attributes to ensure that a user is allowed to see theirs. We do this in the Google Cloud Directory Sync.

Sitecore Custom role permissions for experience editor

We need to add a custom role which should have edit permissions on the page but should be able to add components\create new content. The user shouldn't be able to publish content or add new pages. He can edit page and add\create relevant components\content on the page. Currently, we've added below roles to the custom role and denied 'create' permission to the role on the entire content tree except for relevant page templates and placeholder settings.
Sitecore Designer
Sitecore client authoring
But while adding content in experience editor user is getting 'you don't have access to add content' error. What should be the exact set of permissions to be able to add content to pages but not create pages.
By default items are denied access and you need grant the specific access on the items in question. To be able to edit an item a user will need the Write permission.
Resources:
The different Access Rights explained
Assigning Access Rights

Login page responsible for different applications

I have a workspace in which I have many applications based on the same schema.
Every applications has his own login page at the moment.
I want to build another application responsible for the login of all the other applications.
The login will redirect the user to a main page that will show the links to the different modules (applications) based on the user type.
Note that only the ADMIN user can see the links to all the applications.
Different types of user will see only the links to the apps that they are authorized to access.
I read other related posts, I know I have to change the cookie name for all the app I want to share the authentication.
But my question is:
If I login successfully with a user different from the ADMIN, I am still able to access all the applications via URL, even if their link is not visible in my main page.
How can I prevent this?
Check out the use of authorisation schemes (see under Shared Components).
If you had an authorisation scheme per application you check on each page so that if the current user was authorised that application. Don't forget that each authorisation scheme would also allow users who have ADMIN access.
Hope this helps.
Just had another thought. Check out this post http://www.explorer-development.uk.com/securing-vulnerability-exploits-apex-part-2/ by Craig Sykes.
Activating Session State Protection and using Checksums would prevent a number of issues for you.