spring security role-based needed for full stack app? - spring-security

I am implementing a basic login app. here are the features:
Upon successful login, there should be a welcome page that shows the name, username and role (manager/user).
If the user has a manager role, the welcome page will have a link to access a restricted webpage.
This restricted webpage can only be accessed by a manager role and not by other user roles.
implement logout functionality.
If the userid or password is not valid, I should remain at the login page with an error message "Invalid userid or password".
All data should be stored in a database.
The application should demonstrate MVC pattern...
my schema:
enter image description here
i am using react js for the front end. i build the backend using spring security with the role-based authorization where certain url can be accessed by certain role. i already do a testing on backend end using postman where i try to access /restricted and it responded with 401 if i use ROLE-USER instead of ROLE-MANAGER by using the mvcMatchers(). now the confusing part is the frontend
i noticed i can do all the necessary validation on the front end. i dont even need to do mvcMatcher() on the backend as i can just load the userdetails and roles and ask react to validate for me! hell, i dont even need to use role-based authorisation. i just need to add extra field in user table named "role" and use that to check for item 3 and display the role on item 1. i just need 1 table, not 3. i can even ask react to redirect to /login if user is trying to access /welcome without login, or disable /unauthorised if user role is USER.
but i dont feel right about this way. i'm confused.
a. whats the best approach?
b. is role-based only applicable to rest-api services, not full stack app? from what i see front end can do ALL validation
back end repo
front end repo

a. The Best approach is to have authorization at the back-end level because your React front-end is not the only way to access the back-end. If the back-end doesn't have authorization implemented, then even if you have validation on the front-end, a malicious user can use any other HTTP client to access the back-end without authorization.
b. Role-based authorization is applicable in all scenarios in which you want to allow access to resources based on user roles, no matter which stack is used.

Related

IdentityServer3: Can it be used "side by side" with existing users/authentication?

I'm new to SSO, so hopefully what I'm asking makes sense. So my current setup is a .NET MVC website using OWIN/cookies (app.UseCookieAuthentication()) and a custom user table (not ASP.NET Identity users).
So I'm wondering if I could add IdentityServer3 only for external providers, but leave all my existing user/authentication stuff as is for "local users". So I see that you can implement a custom IUserService to lookup users against your local database, and I think I got that working, but I'd like to even avoid that. And I'd like to avoid themeing the IdentityServer login screen. So something like this:
User hits up page with [Authorize] attribute.
User is redirected to my existing login page (not IdentityServer stuff)
Then my login page would have the external provider button(s) to login with external providers.
Is that possible? Or do you have to run your local users through IdentityServer3 also? I noticed I get an error if you don't provide a IUserService and don't use UseInMemoryUsers() either.
So from following various guides, I have this in my Startup.cs: app.UseIdentityServer(), app.UseCookieAuthentication(), and app.UseOpenIdConnectAuthentication() with Authority set to my IdentityServer endpoint.
Hopefully that made sense, Thanks!
Gonna answer my own question if it helps anyone else. The important piece here is AuthenticationMode in OpenIdConnectAuthenticationOptions. AuthenticationMode.Active is what will redirect the user to your OIDC provider anytime they hit an action with [Authorize].AuthenticationMode.Passive will allow you to use your OIDC provider as an additional authentication method. You want to follow the examples with ExternalLogin() and ExternalLoginCallback() controller actions that issue challenges to the provider and then match the authenticate user with your local user.

How to add additional custom criteria for authorization or token creation in Spring Oauth?

We have implemented Spring Oauth authorization+resource server that can be used for external applications.
Now we would like to add custom checks before some oauth calls returns in the authorization server, most importantly for the authorization code but also before allowing returning a token sometimes.
An example use case might be that which users that are allowed to login for a specific client_id might vary and if not allowed this should generate a redirect back with an error.
So for example a user might trigger a login from a third-party app, redirected to our authorization server and shown a login page, however after login it is discovered (through our business logic) that this specific user is not allowed to authorize access to that specific app/client id.
What is the best way to achive this result in a way that is consistent error handling in Spring oauth?
Also, a related question is also how to resolve the client details before the login screen shown so more specific client details can be shown when logging in?
We could parse the client_id parameter manually but maybe there is a more elegant way to hook into Spring oauth to solve this?
(sorry for dual question but its sort of related and the first question is the most important one)

Why using an authentication_token instead of the normal authentication process?

I have a Rails web application, and I want to build a JSON API as well so I can have mobile applications bound to it.
I've been reading a lot about it, and I don't get it why so many people prefer to activate authentication_token authentication instead of the normal authentication process that Devise offers us.
So, the question is: why use authentication_token ? Any performance reason ? Any security reason ? What is the best way to authenticate through an API ?
authentication_token is basically used to authenticate user from outside
i.e. say you sent user a email containing the activation link containing the token, so when he clicks the link, he directly gets logged in.

Two tier sign in with Devise (Amazon style)

Let's imagine I have following scenario
User receives an email that there is a new item waiting for her
Clicks on a link and is able to either confirm or reject item (details skipped)
Can then access a list of all her items
The trick is that I would like to allow all this happen without user signing in but then limit access to other parts of the website (like sending an item to another user)
How I see it is that:
when user clicks a link she is signed in but only on tier 1 - with access only to confirm/reject action and read only to index of items (that's when Devise session is created)
when user wants to access other part of the website the sign in page is presented
when user comes to the website just by typing in the url http://example.com and wants to access own account she is asked to sign in.
after sign in session is "promoted" to tier which allows full access
after some time of inactivity session is downgraded to tier 1 for security reasons
My inspiration comes from how Amazon works - you can access in read-only most parts of the account but before performing any destructible actions you need to sign in.
Does anyone have any experience with such approach or can share some blog posts, etc?
I didn's find anything on SO and Google mostly returned things about two-factor auth which is not the case here.
I also understand that there are security concerns with links in email.
I have implemented a very similar behavior few months ago. I don't have very interesting resources to show you but I can explain a bit how you could organize or think about the problem to solve.
Description
For the problem you state, it looks like once you have identified a user, you have two different states you can give him:
limited access (perform certain actions, read most of the resources, etc)
full access (allows them to do anything they would normally do).
Having stated that, what you need to do is figure out in which cases you will give a user each access state (for example):
signing in with email token -> limited access
password -> full access
authentication_token -> full access
omniauth -> full access
After that, you will need to save this information in the user session. This should be done anytime the user is authenticated, as you will know what strategy was used to authenticate the user.
To know if a user can or cannot perform an action you will need two things, know what the user can do, and the current "access state". Depending on those you will decide wether the user is allowed or not to perform a certain action.
Whenever a user can't perform an action and is logged in with limited access you should bring him to the flow for verifying his crendetials. This flow is pretty simple, almost like a sign in but just with the password. Once you verify his crendetials you can upgrade his authorization to a full access one.
Implementation details
I recommend you to create a Authorization model which will represent the "access states" that I mentioned. This model will have to be serialized in the session so you should be able to build it from a simple structure and serialize it again into that structure. The simplest the better (a boolean flag, an array or maybe a hash). For the case mentioned, it looks like a boolean would do the job.
Regarding implementation details, I recommend you implementing this with a Warden after_atuhentication callback.
You could implement this with CanCan by creating you own Ability that would be built with an Authorization instance and a User instance.
I think you're confusing authorization and authentication. Devise is an authentication solution, meaning it handles the "proof me you are who you say you are" part. Authorization is the "Ok, I know who you are, now let's see what can you do". Devise doesn't provide an authorization system beyond the simple "logged/not logged". If you need a more complex authorization system, use an authorization gem. CanCan is very popular.

Setting up a private beta for a website

I'm trying to setup a "private beta" for a site that I'm working on. The site uses open id. I don't want anyone to even browse the pages if they aren't part of the beta. What's the best way to implement this? Any suggestions?
For example:
When the site goes live, users will go to http://www.mydomain.com which will not require them to log in.
For the beta I want to restrict access. Users that go to http://www.mydomain.com will be redirected to a login page. Anyone attempting to access ANY PART OF THE SITE who is not authenticated will be redirected back to the login page.
I could stick [Authorize] attributes all over my controller actions, but that seems stupid.
If you're using ASP.NET MVC, it comes with authentication/authorization out of the box. You should be able to use that to setup authentication on your site.
Alternatively you could setup app server settings - IIS lets you setup username/password on a specific site it's serving, regardless of what the actual application may do. If you have access to the app server this might be the best solution.
If you're using IIS6, you can setup authorization easily. Right-click on your site > Properties > Directory Security Tab > Authentication and Access Control > Edit, and enter a username/pwd of your choice. Done.
The real question is how are they being invited to the private beta?
You could setup a password which drops a cookie much like serverfault.com does.
OR
If you know who you are inviting: you could add them to the system before hand using the email/login information that you already know about them (assuming you are inviting them via email)
I have implemented a function in a web application a while ago where we go the possibility to block access to the full website unless the user was an administrator (which in our case meant that the user account was a member of a specific group in Active Directory).
It was based on two things. First, all pages in the web application inherited not directly from the Page class, but from a custom page class in our web application. Second, we had a value like this in the appSettings section of web.config file:
<add key="adminaccessonly" value="0" />
The custom page class would check that value when loading. If it was not 0 it would redirect to a page (that did not inherit the same custom page class, though) informing the user that "the site is not available right now". If the value was 0 the page would load as usual.
In that application we used this to be able to take the site "offline" when we deployed a new version, giving us some time to verify that all was good before we let in the users again.
Best way are invitation system (based on invitation code) or manually confirmation access after create profile in your system. imho
Or you could host the site on a private server, and set up a VPN to use it. Depending on your resources and needs this may be the easiest and most secure way to do what you want without modifying your codebase.
OR alternatively you could use Apache or IIS to force authentication on access to the website directory. Keeping the authentication info in .htaccess for a while.
Even though you use open id authentication, you may still need some form of authorization mechanism. The simplest form would be a user-roles system in your database that assigns different roles to users
In your case, just assign the private_beta role to your private beta invitees and ensure you your authorization mechanism that all users have private_beta privilege before they may continue.
If you don't want to provide authorization for the public site (where everyone can do everything, once authenticated), then, you may only need to do a quick-and-dirty post-processing (for private beta only) on your open_id authenticated users to check them off a short list (which you can store on a text file.

Resources