I'm building an Identity Data Provider (IDP) to centralize my users' accounts and provide them with Single Sign On (SSO).
The goal is to allow our clients to navigate through our applications without having to reauthenticate and find their data back.
We built that central service with Laravel Passport. Authentication and SSO are working fine. Our applications retrieve users' data and store local user records for their own custom needs, filled with data from IDP.
But now, the question is : how should we keep local user records up-to-date with the IDP ?
We already set up a syncing mechanism driven by users' activity. But we'd like to go further and have a mechanism not based on user's activity. The goal is to be able to update an application local user on IDP data updates without having the user logging in the client app.
I can't imagine our central IDP sending requests to each application's API. I guess it's better being "one direction only", from client apps to IDP.
I was thinking about a "broadcasting" method based on websockets. The central IDP could send "user update" messages through a websocket. Clients apps could listen to this websocket and update their local records if needed.
What do you think about that ? Any experience feedbacks on that topic ?
Thanks for your help
Related
within Cumulocity (hosted) we have our own application with plugins written using AngularJS.
From this application we want to send a request to a microservice that we have running as well.
However, the microservice ask for authorization information when sending a get request. (How) Can we overcome this?
The reason we have decided to do it like this is so that we do not have to expose critical information.
Thanks
All microservice invocations require authentication with a valid user in the tenant.
If you really want to expose something without authentication, you can create a dummy user with no other permissions in the tenant and hardcode the credentials of that user in your AngularJS code. However, this is a risk for you, as it makes it easy for malicious users to bombard your tenant with potentially charged API requests (depending on your service provider pricing model).
If the information that you want to expose is not dynamic (maybe tenant configuration or so), you could upload such information as part of a web application. E.g., you upload a "config" application with a single file "config.json" and load that from your AngularJS application using the URL /apps/config/config.json. Not sure if that is your case.
All requests to Cumulocity including those to microservices must be authenticated fully. There is no way to access a microservice without valid credentials.
The platform needs this information to determine if the user and tenant have sufficient access rights to perform the requested action. Even if your microservice does not require special permissions to access. Cumulocity will at least need to check if the originating tenant is allowed to use the microservice.
Background:
I have a basic user database with username(email) and password. The users are able to sign in to a website of mine with these credentials. From the website they get a link to different services they have access to, but with different username/passwords. So they click the link "Open My Service X" and they have to login with their service unique login credentials. I do have the users service login-username. So I can map local-user <=> service-user.
I want SSO between service X which has support for SAML and my website.
Question/Problem:
I want the users to login with their user/password in my database, then single sign on towards service X where service X has support for SAML. I don't want a user to be able to sign up for a new user account to my website using the SAML support in service X. The user must already have an account in my database.
So my question might be rather vague, but I'm having a hard time to grasp how this can be achieved?
I was thinking of letting my webapp become a SAML identity provider, so that the SSO request are transferred back to my webapp and verified for their service-user. Would that be correct approach?
You're on the right track with your SAML IdP. There are basically three parts involved. Your email database (the identities), your existing application front end and the remote services which support SAML. Usually it's SAML2 these days.
To get single sign-on (SSO) across your portfolio of apps (your own app and the remote services) you could install an IdP like the Shibboleth IdP and convert your app to use it instead of using email/password to login. That would take a fair amount of work as you'd have to convert your app into a SAML SP, just like the remote services.
An easier way might be to only use the IdP for SAML to the remote services and get the IdP to recognise that your users are already logged in with their email/password. Cookie? So the IdP should never display a login page as it would recognise your app's cookie and match that with a user in the database. It then releases SAML attributes to the remote service based on that user's information. That also covers your use case of not allowing account creation via SAML from a remote service.
That would mean you might end up with the following URLs:
https://yourapp.com/
https://yourapp.com/idp/
Your users login with the first URL as normal and the remote services use the second URL. That way your app cookie will be visible to the /idp endpoint but you'd need to write code to match that with a user in the database.
I am designing a service oriented application where the communication to the database is distributed across multiple services (Authentication service, some service for auditing and other for accessing the db and doing CRUD operation ... etc).
Say a user login to the app using his id and password, the app then talk to the auth service and find out if the information are correct, once done the user want to insert some data, now the app use another service to fulfil the user request. How can the other service now that the user is an authorized user to use the service.
Your use-case seems very similar to what SAML addresses.
Also look at OAuth.
If these standard mechanisms don't work for you, you can at least develop a mechanism where:
The authentication service returns a token on successful login. The
caller app should then be able to use this token to access the data
service and other services.
The data service should be able to independently validate the token (possibly with the authentication service).
You might want to ensure that the tokens remain valid only for a certain duration or certain number of invocations
What this avoids is the need for every back-end service to allow access to the app without using your login details.
Also see: What is token based authentication?
I have two different client apps written in javascript connecting to two different web api. I am trying to implement identity server 3.
Is it possible to have identity server behind my web api owin
authentication api end point. In other words, is it possible to
route /token endpoint from owin in web api to call /authenticate
endpoint in identity server?
Is it possible to audit log to db in identity server including
failed request along with user's ip and browser agent. Also is it
possible to log user's ip even if i am calling from web api as my
web api is being called by a user using browser?
In my case should i keep two different user base for two different
projects or move all my users to identityserver. If i move all the
user info to identityserver, how am i going to handle all the joins
with other tables in different applications or should i keep a copy
of user with minimum info such as id, email and name?
It makes little sense to first call a web api and deal with authentication during that call.
Your client apps should first redirect the browser to IdentityServer where user would log in and be redirected back to your client app along with either access token (implicit flow) or authorization code (AuthorizationCode flow), depending on the client app having a back-end or not. Then, your client app would make requests to the webapi, passing the access token in the Authorization header.
As for different user bases, one approach might be to implement specific IUserService for each user base and either send a hint about which one to use in the acr_values or tie it to specific clients registered in IdentityService. Again, depending on the requirements.
Is it possible to have identity server behind my web api owin authentication api end point. In other words, is it possible to route /token endpoint from owin in web api to call /authenticate endpoint in identity server?
Yes and no - you cannot reroute those requests, but you can host identityserver in the same application as a web api. In Startup.cs, map a folder to identityserver.
It's not a good idea to do this, first of all, which api of the two will host idsrv? What if that api goes down and takes idsrv with, then the other api does not work anymore.
-> host idsrv separately, make both apis and both javascript apps clients in idsrv, login to idsrv from the javascript apps (=SSO) and use bearer tokens for the api
Is it possible to audit log to db in identity server including failed request along with user's ip and browser agent. Also is it possible to log user's ip even if i am calling from web api as my web api is being called by a user using browser?
Yes, this should be possible, check the logging implementation for idsrv, at the least you should be able to plug in a provider that writes to a database.
In my case should i keep two different user base for two different projects or move all my users to identityserver. If i move all the user info to identityserver, how am i going to handle all the joins with other tables in different applications or should i keep a copy of user with minimum info such as id, email and name?
Idsrv does not need to have all the user info, just an email-address is enough, you can use that as link to the user data in your api databases if you use that as unique identifier.
I recently started a new project using different carefully-chosen technologies, my project is built as follow :
The approach is API-Centric, which means I'm building a website and an iOS app communicating with an API written using Symfony2. I've successfully managed to write my API, and it is perfectly working.
To gain access to the services provided by the API, the main actors (the website users, the iOS app users and the developers) can authenticate theirself in several ways :
Clients can gain access with a login/password couple through the website interface which is communicating directly with the API through AJAX to validate the provided credentials and set a session. So, when someones logs in our website, they have automatically access to the API as well.
Developers can authenticate theirself through the API using HTTP-Basic over SSL, which will as well generate a session and give them access to the services they are authorized to call.
Also, Developers and clients can gain access to the website and the API using their facebook account through the Facebook Connect functionality. This deletes the step where each actor has to create an account on our website.
So basically, the credentials are provided either through HTTP-Basic or using the Facebook Login functionality.
Now that my authentication system is working and that my clients are able to access the website, I would like them to connect to a real-time server when they log in. Like in Facebook or Google+ if you want where the real-time server manages chat and push informations.
In this case i'm using Node.js and the powerfull socket.io library to manage everything that deals with the real-time side.
Of course, the real-time service will need some credentials to authenticate the user since he is authenticated to the Symfony security system with a session but is not authenticated against the real-time server.
A solution I've been thinking about would be to use the PdoSessionStorage in my API (Symfony side) and store all the active sessions in a database such as MySQL or PostgreSQL. Doing so, I would be able to send to my real-time server the session id generated by symfony and check on the database if the session id provided is correct or not. If he is I'll let the user access the services provided by my real-time server and associate his session with an identity.
But I really don;t know if this is a good solution and I would like some more experienced advices on this and on how to deal with this issue.
Note : For some reasons, I cannot implement OAuth even if it could be a solution to solve this issue using a Single Sign On approach.