Escaping a few views from authentcation (Guest Users) in Django-rest-framework - django-rest-framework

I've set a default authentication class as I needed most of apis to be authenticated before being accessible. However, I need login api to be available to all user.
I don't see negative authentication class in django-rest-framework.
How do I let my login api to be available to guest users while not making view level authentication_classes declarations?
This problem arose because I'm not using django's User model. How do I create AnonymousUser instance for my custom User model (not inherited from django's user model) and then permit that user to interact with the apis?
EDIT
Mark Galloway reminded me of mentioning the same issue with permission_classes.

Authentication alone does not prevent a user from accessing resources. A combination of authentication and permissions is the actual determiner for this. For example, if your permissions are set to 'permissions.IsAuthenticatedOrReadyOnly' then users who fail to authenticate (eg/ no valid token) can still access the retrieve and list endpoints.
How exactly you want to define your permissions is up to you. For most of my implementations I use a global permissions setting but tag my log in endpoint with view-level AllowAny permissions. Additionally, view-level authentication for a specific is the only way to override global authentication settings.
For example:
class login(viewsets.GenericViewSet):
permission_classes = (permissions.AllowAny,)

Related

How to access user specific resources in webapi when the access token does not include user info

I have implemented OpenId Connect for authorizing my multi tenant app, I have obtained both the Id Token and the access token. The access token does not contain any claims, but I would like to access user specific resources in the web api.
For example, in order for a user to access a certain resource, 1. They must be a tenant admin and 2, they must have permission for that resource (say a specific job post).
My questions.
Do I send the user permissions to the webapi in the request body/query and the webapi trust those permissions?
Should I use the access token to call the Identity Server to get the user information, then proceed if the user has the permissions?
Any other options?
You can always add the necessary user claims inside the access token, and by doing that, you don't have to pass that information separately. You use ApiScopes and APiResources to control what user claims that goes into the access token.
See my answer here: ApiResource vs ApiScope vs IdentityResource
To complement this answer, I write a blog post that goes into more detail about this topic:
IdentityServer – IdentityResource vs. ApiResource vs. ApiScope

Spring security - Is username and password must for creating authentication

I am using spring security to authenticate a user. The user is authenticated by a third party and will already be authenticated when he reaches my application.
To implemented this, I have simulated a Authentication object.
I don't have any username and password and instead just have identifier. I check if this identifier is valid or not using my custom code.
My query is as follows:
Do I require a username and password to create a authentication object.
I have done without providing username and password and my application works fine.
I just want to ensure that I am using spring-security correctly.
Is there any impact of not putting username and password in Authentication object. I read below in AbstractUserDetailsAuthenticationProvider:
// Ensure we return the original credentials the user supplied,
// so subsequent attempts are successful even with encoded passwords.
I have also implemented a custom provider.
What does above comments means?
Is my approach correct?
The Authentication interface in Spring Security represents a token for carrying out validations against the configured security rules and the current call context. This interface has six methods of interest - getPrincipal, getCredentials, getDetails, getAuthorities, isAuthenticated and setAuthenticated.
Since you are authenticating users on your own, you should be mostly concerned with calling setAuthenticated(true) at an appropriate stage in the flow so that isAuthenticated starts returning true to indicate an authenticated user. Additionally, you may add GrantedAuthoritys to the Authentication for any role-based checks to work correctly.
However, it will be useful to make sure that getPrincipal (username in the case of form login) returns a unique value per user or per session. This will prevent the possibility of user sessions getting interchanged due to non-unique principal, which is used by the framework to identify users uniquely.
You may leave getCredentials and getDetails unimplemented. In fact, getCredentials (password in the case of form login) should be left unimplemented in your case because your application does not have the credentials used to actually authenticate the user; plus, it is a security risk to keep the credentials around after the user has been authenticated successfully.

How to force an MVC application to populate the User.Identity.Name value when using Windows Authentication

I have an MVC 3 application which is to be used for both anonymous and authenticated users.
This is accomplished by configuring IIS authentication mode to enable both anonymous and windows authentication, and then setting the authentication mode web.config setting to "Windows" and applying a custom authorization attribute selectively to actions that require the authentication check.
The issue is that in some actions I don't need to apply the attribute (so anonymous users can access it too), but in the case that an admin user is browsing it, then I want to retrieve his User.Identity.Name value.
The application is behaving unpredictably, in some instances, once the user has been authenticated in a previous action, then the User.Identity.Name property remains available for the rest of the user's session. However, in other instances, it's coming up as an empty string.
So, how do I actually tell the application to "go and authenticate this user"? If the Authorize attribute can force the authentication of the user, then how can I achieve this same effect on demand within an action?
thanks for you help,
M
If the Authorize attribute can force the authentication of the user,
then how can I achieve this same effect on demand within an action?
By doing the same as the AuthorizeAttribute does:
return new HttpUnauthorizedResult();

Programmatic authentication

I am using Spring Security in my application.
I have all the pages secured. But couple of URL needs to be available both for system user and anonymous user.
But anonymous user should not have direct access to the URLs. He gets a link with unique token and gets access to some URLS if this token is valid.
What I want to do is:
In controller check if token in URL is valid
If it is - authenticate user in the system programmatically using some predefined login and password. This user will be configured to have authority to access necessary URLs.
The question is:
Is this a correct approach to perform user authentication programatically with some roles in controller if token is valid? Is this safe approach?
Security is an aspect. An aspect can be decoupled from your main code (controller) to reduce code duplication and improve flexibility. Move authentication code from controller to new filter (be sure that this filter executed after spring security filter chain). You will be able secure new URLs via web.xml (zero lines of code).
I think the better way to do this is:
move the shared operations into service layer
define a controller for those anonymous user and make its authority
as anonymous
check the validity of token in this controller
if valid, call some services method to perform the operations.
render the result in this controller

Spring Security Recommended Design To Request User Login to Different User With Different Role

I have the following use case and need recommendations on the proper implementation. To be clear can this be done through configuration or do I need to implement new code?
Business Use Case
The business wants to allow a user to login via social media sites and access some of their pages. But in order to access pages that deal with $$ the user must login via the applications local account.
Technical Use Case
Allow users to login via Facebook or other provider and provide role USER_PARTIAL_RIGHTS
If user accesses a page with role USER_FULL_RIGHTS prompt the user to login to an account that is a local JDBC stored account.
This authentication must also ensure that the page is protected by USER_FULL_RIGHTS role and not other roles.
I am using grail spring security plugin, but I am expecting to have to customize the plugin.
So what are recommendations for doing this? A couple of ideas that I have are:
Technical Ideas
custom spring access denied handler
custom access denied controller instead of the stock jsp page
From what i understand from your question, here is my suggestion.
For login via Facebook use Spring Social. Here is the documentation. The implementations are straightforward. Write a custom signin method and set the authorities for partial rights, something like this:
public void signin(String userId) {
authorities = new ArrayList<GrantedAuthority>();
//set your partial rights authority
SecurityContextHolder.getContext().setAuthentication(new UsernamePasswordAuthenticationToken(userId, null, authorities));
}
And do a method level security implementation using the #secured annotation to access the page that needs full rights. Something like this
#Secured("USER_FULL_RIGHTS ")
yourMethod(){
//code
}
This would prompt for a login where can use authentication from applications local account.
What we ended up implementing is a controller that looks at the role and redirects the user to the correct landing page. Kinda messy, but it works.
Collection<GrantedAuthority> inferred = SpringSecurityUtils.findInferredAuthorities(SpringSecurityUtils.getPrincipalAuthorities());
if(ifAnyGranted('ROLE_FOO', inferred)) {
redirect(controller: 'foo',action: 'home')
return
}

Resources