How Custom Authentication Works in MongoDB Stitch - mongodb

Following MongoDB Custom Authentication, it is given that any JWT Token with the minimal below fields works with the MongoDB Stitch Authentication. Also, token needs to be issued by External Authentication System
{
"aud": "<stitch app id>"
"sub": "<unique user id>",
"exp": <NumericDate>,
}
I've tested this and it works as well
Created Stitch App and enabled Users with Custom Authentication Provider
Generated Sample Token through Jwt.io with the below inputs. (Use same algorithm and key as configured when enabling Custom Authentication Provider, Here it is, HS256 and the )
It works in the way,
It is validating the users in MongoDB Stich Users Collection with the unique value provided in sub: "sub": "<unique user id>" and if the user is present then it returning the Object Id for that User.
If the user is not present then it is creating one against the input and returning the Object Id.
Queries are,
Why it is creating a new user instead of returning login failure, which in turn works like any user can log in with any credentials on demand?
If MongoDB Stitch Custom Authentication involves External Authentication System to issue JWT, where the user data will be actually stored when user registration? - MongoDB Stitch App Collection or External Authentication API System?

Here is the response from MongoDB Support
Why is Stitch creating a new "User"
The "User" Stitch creates in this scenario is an internal user. This "user" also contains the user data and metadata provided from the JWT and is not stored alongside your other collections in the Atlas cluster your application is linked against. Note that this "user" is not accessible to MongoDB without using a trigger or other function to load it into the database.
Why isn't a login failure returned
A login failure is not being returned because the custom authentication provider is only checking the signed JWT from the external system against its own copy of the signing key. If the signatures match then the login is deemed successful.
It is the responsibility of the external authentication provider to fail the login; not Stitch.
Where will the user data actually be stored
The user data should be managed within your database. The most efficient way to integrate this with the Custom Authentication provider is to use an Authentication Trigger on Create and/or Login operation types. This would allow you to run a Stitch Function any time an authentication event is triggered.
There is an example of using authentication triggers on the MongoDB blog which may help explain the process further.

Related

AWS Cognito with external IDP (SAML) for Post-Signup/Signin Actions

I also need to add the created/updated user into a users-table of an RDS-database, and the described workflow does not describe such a scenario at all.
Is it possible to react to the create/update of a cognito user within this SAML-workflow, by also updating an applications database-table with the new data?
--
In the docs of AWS Cognito in the Chapter "SAML user pool IdP authentication flow" there is following part written:
6. After verifying the SAML assertion and collecting the user attributes (claims) from the assertion,
Amazon Cognito internally creates or updates the user's profile in the user pool.
Amazon Cognito returns OIDC tokens to the app for the now signed-in user.
see: https://docs.aws.amazon.com/cognito/latest/developerguide/cognito-user-pools-saml-idp-authentication.html
this part does not seem to recognize the scenario i described in my question, and there is no link/hint to such a solution given.
In order to perform additional actions to customize the Cognito user pool workflow, you can use Lambda triggers.
In your particular situation, there are triggers and triggerSource values you should look for regarding Sign Up and Sign In for federated users, as per documentation, namely:
For SignUp:
PreSignUp_ExternalProvider this is called before the user is created in Cognito, allowing to perform some additional actions, normally validations.
PostConfirmation_ConfirmSignUp is invoked after the user has been created and confirmed in Cognito. This would be where you'd create it at the RDS Database.
For SignIn:
PreAuthentication_Authentication similarly to PreSignUp, useful for additional validations, but for Sign In.
PostAuthentication_Authentication called after a successful authentication. This is where you would update the User at your Database.
Also keep in mind that the Updated date of the user will change at each new sign-in due to this (source) :
Amazon Cognito must be able to update your mapped user pool attributes when users sign in to your application. When a user signs in through an IdP, Amazon Cognito updates the mapped attributes with the latest information from the IdP. Amazon Cognito updates each mapped attribute, even if its current value already matches the latest information.

Change user DB connection at runtime in Keycloak user storage SPI

We have a single Keycloak realm configured to be used from a different server for authentication. I am implementing Keycloak user storage API to look up from user database. Each server can have a different user database.
I can determine the database to connect based on request details but not sure how can I get the same in user storage API.
Update:
I can also do with identifying client ID.
Another option can be to let the SPI implementation invoke a REST API to validate credentials to simplify keycloak configuration. However this would also need some identifier to determine database.
Please advise.
Keycloak does not provide request URL to user storage SPI implementation. It does provide realm and client IDs. If required, realm or client values can be used to determine required action.

Flask-OIDC | How to call a specific function after the user logged in

I built a login system using Flask OIDC and Keycloak. In my system, there is some endpoints decorated with oidc.require_login() that calls the Keycloak login page.
My goal is, after the user successfully logged in, my system checks if the user name exists in a specific database.
How can I set a function to be called every time someone successfully logged in with Keycloak and do this verification at the database?
According to your needs there are several ways to create the user in the backend.
The easiest way would be to just check the JWT token on every request. OIDC is based on JWT and that token is available on any request (which should already be done to find user roles etc). So your application can check that JWT and extract the username from it (see here for details about the JWT format). With the username you can check your internal database and create the user, if it doesnt exist. But at that time you'll not have access to any user credentials any more. It is just SSO and you need to trust Keycloak and the JWT... Also - you'll never be informed, if the user will be deleted in Keycloak, which could be an issue.
There is a callback API in Keycloak in form of the Admin URL per client. But the documentation is not clear. It says: It’s used by the Keycloak server to send backend requests to the application for various tasks, like logout users or push revocation policies. But I cannot find a complete list of "tasks". I saw only logout events. see Keycloak documentation and the documentation only talks about that. If I add an admin url to a test client, I did not get any requests at login time.
a different but more complicated way would be to create your own UserStorage SPI in Keycloak. It would be Java of course, but only some classes. There is an HTTP example or have a look at the LDAP user storage SPI, which supports registration too. If you choose that for your realm and a user tries to login to Keycloak (Login form), the SPI can call your backend to check the user. It also could be "used" to create the user in the backend by checking the Keycloak local storage and only if there is a local Keycloak user, call the backend. That isn't the reason, why you should implement the UserStorage SPI, but it's possible. If you think, this is a good idea, I would prefer to use your backend storage as the one and only storage or build a different one, that then could call your real backend in case of a new user. I would use this one by not using Keycloak local stored users but, by using your own database.
next (maybe last one). You can write an EventListener SPI to read all events and only filter the login events, see here and here. I think, that would be the easiest one. But be aware. In that case, the HTTP call to your backend coming from the event itself is based on a normal HTTP request (without OIDC at that time).
The last two examples create a JAR (which is explained in the links). That JAR with the SPI must be deployed in keycloaks standalone/deployments folder. The EventListener should be active by default, the UserStorage SPI must be activated per realm.
But - be aware - Keycloak/SSO/JWT - should not be used by creating users in multiple backends. Syncing the users between all backends in a SSO environment is maybe the wrong way. Most information is located in the JWT or can be called by a backend from one central user identity management. Do not store a user more then once. If you need the user reference in your backend - link just to the username or userid (string) instead of a complete entity.
There is no direct way of doing this, other sotfware like Openam, Okta allow you to trigger specific flows in a post-login configuration.
In keycloak, you can try to create your custom authn flow(using Default Identity Provider, its the only option that allow a redirect), and then select this flow in your Identity provider in post login flow.
The idea here is that after login, the user will be redirected to a link ( an api call that will verify his presence on the external database, and sent him back to keycloak once the verification is done.
More info here

How to check authenticated status server side with ionic cloud Auth

I'm evaluating whether to use Ionic's cloud Auth service and it seems like it's relatively easy to implement client-side, where you can check this.auth.isAuthenticated. You can also set the user info from the client side as well.
However, if I want to do check their identity server-side, such as check that a user is authenticated when they call my custom api to post a comment - how can I get some sort of token (preferably a JWT token) that I can use to validate their identity server-side? Assuming we are using email/password authentication.
Also - using their send notification on a user's birthday example, how can I query the user data in ionic cloud's database to say find all users who have a birthday today. Can I export out the user data in any way if I want to migrate away in the future?
You should implement a JWT authentication service server side.
In other words when the user is authenticated, the app can send a JWT token to the server which should be evaluated to trust the remote user.
For more info reads: https://docs.ionic.io/services/auth/custom-auth.html
A php example here: https://github.com/driftyco/custom-auth-examples/tree/master/php
Regards from Italy

Correct workflow of a REST API for mobile app authentication

I am in the process of building a REST API for mobile app developers to be used on a web application built using Zend framework. My first task is to create a service for authentication/authorization. I have read lots of related questions here on SO and would like to sum up what I am doing:
There is no session or cookie involved, so a typical web app method
of checking the logged in state of the user doesn't work here.
With each login request, the username and password is received and a
random string is generated and saved in the DB against the username.
Also, this string is returned with the authentication request.
This user token is sent along with any request that needs authentication.This token is matched against the stored value in DB and if matched, only then the user is allowed to perform the required task.
On logout, the token value in the DB is reset to blank or NULL.
Is this the correct approach ? Won't it over load the DB because with each request, a select query is run on the DB to check for the token value ? If you could provide any tutorial link, that'd be much appreciated.