For a Project I am working on I require some sort of SSO mechanism between applications. It doesn't have to be complex and it's not required that I use OAuth2. Right now I am unsing Laravel and am thinking of Sanctum. I know that Laravel Passport exists and am considering it too. This question is not really about the technology I need to use, but about understanding how a clean SSO workflow might look loke.
The concept I came up with looks like this:
I have a web-application A which has a database with users. This application is supposed to handle all authentication and provides an input mask.
I have a web-application B which wants to ask for authentication. The application B redirects to the input mask of application A.
If the user correctly enters his user data into this input mask on application A, the login is preserved on application A (probably through cookie) and a token is generated and passed to application B.
Later, when I create an application C, I can redirect to the same inpit mask on application An again, where the login is still preserved, so application A can pass an authorization token to application C without the user having to re-enter his login data.
I see one weird problem with this structure: In step 3, after the user inserts his login data, the token must be passed between two projects, and I can not guarantee that they are on the same domain or can share a database. So it seems the only way to pass the token, is to put it as URL parameter when project A on domain A redirects back to project B on domain B. Project B could then take the token from the URL.
But this seems like dirty programming to me, but I can't think of a better solution.
Related
Assume I have a database composed of user and projects. A user has a one to many relationship with projects. The user can do operations using rest endpoints.
The problem is:
how can I verify that this user owns this resource?
I don't want a malicious user to change an id then suddenly he views another person's project details/images/etc. Think of it like a social media (my app is not a social media but trying to illustrate the issue): where you can view only your images but not another person's images despite having the same "status".
Most spring-security blogs online is using a role based approach. I have no idea what to even search for in this case (tried multiple search queries to no avail).
One option is to run some sort of multijoin query on every resource request/operation till I reach that resource id and check it's owning user to check if it is the logged in user. However, I am not sure if this way is efficient since there are multiple tables in a chain in the real app (could have a lot of joins if I go this way manually; example: user -> project -> tasklist-> ... -> Note; deleting a note would trigger a large chain) or how to make the "authorizer" use it.
what are my options?
In case it matters:
I am using spring-boot + hibernate/JPA + spring-security
Spring Security has the following concepts:
Authentication:
Proving the an actor is who it vouches to be. Authentication is done using credentials, where credentials can take any number of forms - username/password, token, hardware key, etc.
You can set up Spring Security with a set of acceptable authentication providers.
Authorization:
Given an authenticated user, deciding if that user has access to a given resource. Where the resource can be:
An HTTP endpoint.
An Java Method.
A property of an object.
What you want to do here is provide a custom authorization scheme.
You can read about Spring Security's authorization architecture here, including how to set up custom authorization. Once you're ready you might ask specific questions as you go.
There are four Laravel 7 projects, Project A going to use project B some routes. For sure project B needs to check if the request is authenticated or not. So there is a need to have a specific auth server for that handle authentication of all 4 projects.
Any idea or implementation of this pattern?
This is a very opinion based question, but what you're describing is similar to a microservice or distributed architecture for your projects.
If you need the ability to have one login or one point to authorise all of these projects, then one OAuth service sounds like the right way to go.
I am currently working across 12+ projects at the moment that are all interconnected, Laravel based, microservices.
We use one Laravel OAuth service to handle logins across all of the projects.
To login to Project A, you are directed to the Login service to login and redirected back.
For API or machine-to-machine communication, we still use the Login service. To do so, we setup a personal access client inside the Login service and then create user accounts for the projects. We then generate a personal access token for each project.
When Project A makes an API request to Project B, Project B takes the authentication token and verifies it is valid against the Login service by calling an api/user endpoint.
If they don't all need one single login, then you may be able to get away without one and just generate local API tokens that consuming projects need to use to authenticate against that project.
My question may be answered here, Are sessions needed for python-social-auth, but I feel as if I'd be making assumptions and would like to be positive regarding my understanding (NOTE: I'm not using django, I'm using mongo express react node, I'm guessing django might come with sessions built in or something). I followed this guide https://medium.com/hyphe/token-based-authentication-in-node-6e8731bfd7f2 to add token authentication and user login to my CRUD web app, works great, users are authenticated properly, routes are protected. However, everywhere I read about the fundamentals of session and session management states that "every web application in the world that maintains user data has to deal with sessions" (source: https://nodewebapps.com/2017/06/18/how-do-nodejs-sessions-work/). Currently, my react client uses setInterval to regularly check if the access token will expire soon enough to receive a new one via the refresh token. Is implementing sessions required for my app? If so, what is it that they add that I am missing?
It depends on the type of application.
If the resources being accessed using a token are not user specific, then sessions are not useful.
However, in a scenario where the resources are unique for different users (e.g. one has to sign in, etc), then it's wise to implement both sessions and access tokens.
Remember that tokens can also be saved within a session. Checkout 'express-session' to implement sessions in expressjs.
We're using Spring Social LinkedIn in a single page javascript app to authenticate a user. We're able to successfully authenticate against LinkedIn, but we're having trouble getting that to integrate with our javascript app. It actually breaks down into two issues:
Issue 1:
We're using one API key for a set or related apps - and we use a single sign-in process. We need a way to identifiy which app the user came from and to send them back to the right app after logging in. The problem we're having is LinkedIn only allows one redirect URL and I don't believe it can carry any parameters (that would probably be the solution if it's possible to carry a parameter like the identifier of the app they're in). Do you know of a way to conditionally redirect the person after login?
Issue 2:
When the user is authenticated, we store the user info in our database, but after that we need the log the user into our app and provide the user with a token. Is there a way after the LinkedIn authentication completes to trigger another call to the server to request the token?
I want to know how can I force a user to log in the the application again if the page is being opened in new tab or new browser.
Edit:-
My apologies I misunderstood the requirement.
I am authenticating the user in my log-in page but not anywhere else. So what is happening because of that, even if i log out of application and type url say bla.com/apple I can access my application.
I figured to prevent this from happening, I have to write a base controller that checks for the right user. Am I moving in the right direction.
Thanks
Addressing the edit -
Authentication can be handled per controller or on individual actions. Simple place the [Authorize] attribute appropriately. This assumes however that somewhere an authentication token is being set. [Authorize] checks against the HttpContext's current User (an IPrincipal).
You mentioned above that you're just validating against a local username and password, in one place, so I'm guessing that no token (session, cookie) are being set?
You have a few options here to get that token stored and persisted across requests:
ASP.Net integrated membership provider (Intro)
A custom MembershipProvider (Example)
Full-on custom flow. (Example)
Each has ups and downs and depends on how exactly you want to handle on-boarding your users. It's hard to answer more specifically because it can be a very large topic (and a very broad question).
Here's the official pages for MVC security.