Not sure if i'm missing something here or if its something that needs to be done in a custom way (Or even if what I'm trying is bad practice). Consider the following Scenario.
A User chooses to log in via a external provider to my IDS4 server.
IDS4 automatically provisions a local user and completes the sign-in of the user. My application is interested in a 'phone_number' claim and so copies this value to its local store.
Later on the User updates their 'phone_number' in the external provider. So now the claim in my local IDS4 store is out of date.
What is the best way to update my local 'phone_number' claim. If i'm using a sliding refresh token there's a chance that it could be a very long time before a user has to re-authenticate against the original exteranl provider and realise this claim has been updated.
In this particular case I have access to both the IDS4 instance and the External provider.
Related
We have built a React web application that authenticates users with Microsoft via OAuth ( #azure/msal-browser package). Users are redirected to Microsoft auth page during signin, and then redirected back to our site once authentication has completed successfully. This is all working as expected.
However, we are in a position where we wish to add a custom PIN mechanism to protect some of our workflows. PINs will be encrypted/salted and stored in our own API, along with the existing mapping between Microsoft/Azure users and our own user state/records. In order for users to change/reset their PIN, we want to force them to reauthenticate with Microsoft before changing their PIN. I have not dealt with OAuth2 in a while, and am not entirely certain how this might be possible (since current auth workflow does not involve our server at all).
Ideally, users would navigate to the "Reset PIN" page and initiate the workflow. If possible, authentication would be handled through a pop-up (so as to not lose page state), which I think is possible as per documentation? If this is not possible, even a redirect to the same page with a specific query parameter (to indicate post-authentication) could work. The user would then be able to change/confirm their new PIN. At this point, a request would be sent to our API, including both the PIN and something from Microsoft that would allow our server to validate that the user did indeed just re-authenticate (proving they can change the PIN).
The primary sticking point is that our API must be able to verify that the user has just re-authenticated with Microsoft! One way to think about it would be that if a user gained temporary access to an unlocked authenticated workstation, they should not be able to perform restricted actions (as they do not know the PIN), nor be able to change the PIN (as they do not know the user's credentials). Yes, yes, I know physical access is effectively a compromise to any security, but this is a higher-level requirement...
I am guessing this workflow is possible, but am not certain how it might be possible. Would we use a different authentication workflow for this particular use case? Any pointers on a workflow we could investigate or use for this?
I can give you some info about how this should work. This type of flow can require a high level of extensibility in the authorization server though.
CLIENT REDIRECT
The client can send the OpenID Connect acr_values parameter, indicating the assurance levels it requires. In your case you would send two values.
CUSTOM AUTHENTICATION FACTOR
The user will perform standard authentication first, eg passwords. Then you would implement a custom second factor that uses the user identity and some custom logic to call your custom API.
ACCESS TOKENS
After authentication has completed, the authorization server will issue access tokens to the client. High privilege claims should only be included when strong authentication has been used. Some kind of scripting would be used here, that can read authentication result attributes.
API AUTHORIZATION
APIs should receive short lived access tokens. If it contains the high privilege claim, you know that your PIN requirements have been met.
CAN YOU SIMPLIFY?
It feels suspect to do your own PIN management. Can you outsource this, eg use a second factor of time based one time password (TOTP) instead? Mobile platforms such as the Google authenticator app provide tested solutions.
I am creating an electron application that connects to an Database and do POST and GET requests to retrieve and insert data into it, the problem is that in the code i have defined my database uri ( im using mongodb)
const uri = "mongodb+srv://<myusesrname>:<mypassword>#cluster0.wqbiu.mongodb.net/query?retryWrites=true&w=majority"
like in the example above, but if i pack my electron app the connection to the database as well as the credentials its visible if someone unpacks the app.asar file and look in the server.js file how i can solve this problem? i dont want any security breaches neither for me or the people that will be using my application, thanks in advance for any answer :)
An application that requires a secure connection to something cannot afford to have any username's or password's hardcoded into its code.
Instead, a procedure of authentication and authorisation is utilised.
Authentication is used to verify the user. IE: They are who they say they are, often achieved via the use of some type of login form.
Authorisation is used to verify the logged-in user is allowed to access the requested resource. EG: Is this user allowed to retrieve a list of all users email addresses from the database.
As a rough guide, a user will login with their username and password. You could use OpenID as well here if you wanted. Once the user is 'logged-in' you could set a cookie or session and save the session id in the DB against the user. Of course, all of this is done over HTTPS.
There are various ways to control the validity of the session such as but not limited to refreshing the expiration date / time every time the user hits the server, auto timeout if the user has not interacted with the server for more than X minutes, etc.
In your app, the user could try and interact with the database at any time, but if the user is not logged in, the server could return the appropriate response and prompt the user to login. Some form of API here is really the way to go.
If the user is logged in then then next step is to authorise the users request, ensuring they are allowed to perform what they are asking before sending a response back. If they are not authorised to access the resource (EG: Edit another user’s post) then an appropriate response is returned indicating so.
As you can see, securing your app will take some work but the result of not doing so could be devastating to you and your users.
With IdentityServer4 I need to allow a single user session per time. If the user authenticates with device A and then with B, session and access token must be invalidated for A and, even better, client A could receive a notification that user has logged out in a second step.The main thing is making the server force invalidate session and token. There are similar questions, one of them redirects us to the following link:
https://github.com/IdentityServer/IdentityServer4/issues/736
where it is explained to use backchannel logout and in the login method of the identity server to obtain the previous IdentityServer sessionID that should have been persisted somewhere. Then I should send logout tokens to all clients.
Another solution is given here
How to Logout user from a particular session Identity Server 4, .Net Core?
telling us to use an ITicketStore implementation to be able to invalidate the session.
The configuration used is IdentityServer4 with authorizaton code flow with PKCE. Which approach is best for my case? Is there another approach where I could simply delete the access token in the id server database?
I think in your case probably a combination of both. In our real-world implementation we combine server-side storage of sessions via ITicketStore (stored in a custom database with sessions linked to user accounts and also storing the list of client IDs for each session) with the ability to trigger back-channel logout of any session at any time (i.e. not just via the default user-triggered mechanism).
In our case we do this to be able to invalidate sessions for other reasons (e.g. password or other security setting changes, a "log me out of everything" feature, impersonation rights being revoked etc) but this approach could form the foundation of a "single session per user" feature should you wish.
I have 3 microservices that hold particular user information including their sign-in credentials (email + password). If the services are A, B, and C then the user "John" will have his info stored separately in all three of these services' database.
Now, the user info in service A is updated at an earlier point of time, and at that moment it is not predictable whether services B or C will definitely be activated to be used by that particular user. So, there is no point in creating an entry in B and C for "John". But, as "John" activates B or C at a later point of time, the system can only have access to the hashed password.
It is to be noted that the service C requires the password to be stored in encrypted form so that it can be decrypted later. So, merely storing the hashed value in all 3 services is not feasible, neither do we want all 3 of them to have encrypted password.
What is a feasible solution to sync the password between the services by maintaining the requirements?
Your approach implies a lot of problems in addition to the one you already described yourself. I recommend to look into Federated Identity (using OAuth2 and OpenID Connect) which fits for Microservices architectures.
Basically, this means that authentication and credentials handling is performed by a separate highly available and scalable service (usually referred to as identity provider or authorization server) that only does that - handling user credentials, identity and access control - and does it well.
It handles login and issues access tokens which are then sent to your Microservices along with the requests. As each Microservice will trust this identity provider it will be able to verify that the token is valid and was issued by this identity provider (this happens by validating the token with a public key). And the token contains information like user id and information about what actions are allowed with this token.
The identity provider can be a cloud service like Okta, Auth0, Azure AD B2C, etc. (see https://openid.net/developers/certified/#OPServices) or host an identity provider on your own, if you are not able to access cloud services, by using ready-to-use libraries available for your technology stack (https://openid.net/developers/certified/#OPLibs).
So there is no need to store user credentials in each Microservice and sync this information between them. I would consider such an approach as an anti-pattern.
The federated authentication approach also allows to solve other problems such as single-sign-on.
If you are new to that topic it can be a little overwhelming at first but it's something you can't get around if you really want to have all the advantages a Microservices architecture can provide.
This article might help you get started:
https://nordicapis.com/how-to-control-user-identity-within-microservices/
I'm building an admin page for an application and have a state value 'authenticated' that flips from 'false' to 'true' after a successful login (which is authenticated on the server) which then shows the actual admin panel.
Are component state values safe from tampering by the client? Basically, if the client can modify my 'authenticated' state value to 'true', they can skip the login and go straight to the admin panel (which I obviously don't want).
I read that React Dev Tools allows the client to modify values yet everyone says "validate on the server" but I am validating on the server and updating my state accordingly, if the user is approved. If it is not wise to have a state value manage this, what is the right way to conditionally show the admin page after a successful, server-side authenticated login?
I think this is an important question since tampering with state values in a React app can have huge negative consequences on data integrity within an app/database.
TL;DR: Either require an authentication token with every request or require authentication through a session.
Never trust users always. One potentially big issue is if you "hide" admin actions behind the admins page without requiring authentication.
For example, assume the backend server uses a REST API to accept commands. In the admin panel you get links to administrative actions like a button 'Delete Everything' that sends a DELETE request to server.net:8080/api/admin/everything without requiring any authentication. If you're a user, you can find that in the code potentially and then send a DELETE request to that address from anywhere without any repercussions.
We'd never give administrative privileges to anyone who would want to delete everything... Because we'll never untrust someone. Right?
Worse, someone might find the server and fuzz some inputs to it, and oops! They manage to delete everything (or even worse, GET everything stored in the database). This wouldn't be hard to do, especially if the server you use to authenticate is the same server you use to issue commands. History has proven "security through obscurity" to be a very bad paradigm. Every action should be authenticated, even if it seems like the actions will be hard to find.
Generally, providing a JSON web token or some other form of authentication token and having the user send that with every request is a good start at least, especially if it has an expiration date. The token would be provided through a separate request with valid credentials.
Sending a token with every single request obviously isn't ideal. There are a couple of other things to try. For servers using PHP, you can probably trust sessions (though very many people who know more than me would probably disagree). In more modern cases, you could try to use Web Sockets, requiring the token after connection. Then only after authentication with the token do you allow the user to make administrative requests.
That way, even if a user knows the exact command they can send to perform any action, the server won't let them without a current session or token. Unfortunately, unless you're already using Web Sockets or depending on a session, it will likely require a lot of changes. I'd consider this to be critical though.
It is always possible to tamper values in the front-end, there is no way you can rely solely on the front end to ensure security.
Your best approach is to implement some form of authentication and authorization on your backend. In this way, even is some users pretend to be admin, they will be blocked when you do the next request to the server.
Perhaps if you can send more information regarding your problem, we can think of a more specific solution.