Integrating with Auth0 - publish-subscribe

I'm in the process of implementing a user management Microservice (MS) and wanted to find out whether what I'm doing is ok. Users are created from the UI, which interacts with an API. The API makes an RPC call to the user management MS, and publishes a CreateUserCommand to an InMem-bus. The consumer then handles the command by then creating a user in the DB, but then I need this user also registered within Auth0 - would the way to go about this be to send a different command to a persistent queue, for a subscriber to pick it up and register that user with Auth0 (persistent queue in case can't reach Auth0). Once that completes successfully, I could then publish a UserCreatedEvent?
Any help with this would be much appreciated.

You have two Bounded Contexts: User management and Authentication.
User management BC deals with the life-cicle of a user (creation, mutating and deletion).
Authentication BC deals with how the users identify themselves in the system.
So, it is a valid assumption that a user can exists even if it has (yet) no possibility to identify himself in the system.
That being said, you should emit the AUserWasCreatedEvent immediately after the User management BC processes the CreateUserCommand because in that moment the user is born. It has an ID, let's name it UserID, so it exists.
Then, this user needs a mean to identify himself and a Saga (or Process manager or whatever you want to call it) catch the event and create a CreateAuth0UserCommand that it is sent to the Authentication BC by calling the Auth0 API. The API respond with some data, possibly including a token; that token is handled by the Authentication BC and it is associated with the UserID.

Related

Discuss - How to make an application registration and OTP generation/verify service to be RESTful

We are developing a portal application where an already existing customer can register their account to see the details of their account (something like you have a credit card and then you register on Bank's portal to see the transactions details - here you are already a customer of the Bank). So when a user is coming very first time for registration then this whole registration flow is not authenticated (as user still doesn't have a username and Password- one will have this after the registration)
We also want that a customer can not have concurrent registrations i.e. if a customer opens multiple tabs (or uses Postman to call our registration API) then only one request should be allowed to register and all other be rejected. For this we have used a registration_session.
So when the first request comes, we find the customer from our master record and generates a GUID/UUID and save it as a registeration_session value against CustomerId as key in Redis (with set expiration). So if any other registration request comes for the same customer then we first search the Redis to see if there is a registeration_session value against the CusrtomerId, and if it exists we will reject this request saying that registration is already in progress.
Now my first question is this: is this behavior is Stateless or not for RESTful APIs? as I am kind of maintaining a request context via registration_session on the server. One may argue that I am not maintaining the application state, true; but if we see it like this: every other registration request has to check the status of any previous registration request - then this means we are no longer having statelessness as per REST principles as now two requests for registrations are no longer independent of each other.
Next requirement is of OTP generation and verify. During registration, we ask the user to identify oneself via an OTP sent to their mobile number (we already have their mobile number from their customer record). A user may request to resend a token multiple times but if use provides wrong input for 3 times, we will put the user's account in locked status. Also we want that once user has verified the OTP check successfully, then any other OTP generation request for the same registration session should not be allowed - as once OTP is verified successfully then to generate OTP again is futile operation (a malicious user may still want to do this via Postman/curl)
Now server has to maintain following information for OTP:
retry count for OTP verification, as the moment it reaches 3, account is to be locked.
verification status for OTP i.e. once it is verified, other request to generate the OTP for same registration session is not allowed
and my second question is this: Is it again violates the REST stateless principal, as it seems we are maintaining the context for requests and every request is dependent on the context of the previous request?
Or is there a gap in my understanding of application state and stored context and above mentioned scenarios do not break Restfulness of an API? OR we can not design Restful APIs for the above mentioned requirements?
Note: I have read enough questions on REST and Context state on SO, but none offered a solution that eliminates my confusion for the specific scenarios that I have asked.

How to handle internal service-to-service authentication in an SOA environment

I'm building an SOA architecture which consists of a simple NGINX-based API gateway which forwards calls from browser clients to an appropriate backend API based on their prefix, for example:
/auth/login will route the call to the login endpoint on the Authentication service
/users/update/widget-1 will route the call to the update endpoint on the Users service
etc.
Each service has its own datastore and follows SOLID design principles. I use events on a queue to keep services informed about interesting things that happen to data that they both know about. For example, both the Users service and the Authentication service need to store the user's email address as it's used for authentication and emailing. So when a user's email is changed I queue a 'user email change' event onto a User Events queue. The Authentication service subscribes to this queue and uses the event to keep itself up to date.
For simple events, I can include enough details in the event to avoid needing more information. But, thinking ahead, what if a lot of changes have happened to the user and I have a datawarehouse that subscribes to every event type. I don't want to start having huge events - I would rather just include enough information for the interested service to use the event to trigger a call to ask for more details.
So the sequence in this example would be:
Client synchronously calls user update with JWT bearer token
User update service validates JWT and uses it to carry out the update
User update service generates a 'user updated' event to the queue, containing the User ID
Datawarehouse picks up the event and calls a 'get user details' endpoint on the User service to get full details of the update.
How do I authenticate the 'internal service call'? I can't use the original JWT as the internal request is happening asynchronously and the calling service doesn't have the JWT. It might not even be valid any more by the time the Datawarehouse requests the user details. It feels like I need some 'internal' JWT - for example, in this case, would the answer be for the Datawarehouse service to have the ability to generate its own JWT with its own private key then the User service checks the signature using the Datawarehouse service's public key? In which case, doesn't this mean each service would have to know about all the other services that could call it?
If it helps, my current implementation uses Lumen for the services with the jwt-auth package to check the JWT at the API level.
Any advice is appreciated, thanks.

Making API requests to a 3rd party that requires authentication

Here is my scenario. Imagine there is a Yoga studio that uses a professional booking and reservation system that exposes an API. Through this API an application can make a reservation for a client. The API takes the client's userid and password to make the reservation. The booking API doesn't use OAuth or any social media sign-ins.
My desire is to create an Assistant Action that would retrieve the list of classes and allow the client to make a booking.
My puzzle is what design/architecture to look towards to supply the userid/password pair required by the booking API.
How have others solved this puzzle?
Should I store the userid/password as "user state" associated with the action?
First, you should have a conversation with the API provider about why they don't provide an OAuth-based solution. This is a security vulnerability waiting to happen, if it hasn't already.
Second, you need to think very carefully about your own risk profile in this case:
Google does not allow you to collect credential information (ie - passwords) through your Action.
Because of this, you must use Account Linking to authenticate them.
This means that you will need something (ie - a database or data store) to manage their account on your side.
This database would be a good place to keep the username/password you need to use for them for the API...
...but it now means that you need to take extreme care about protecting this database.
You don't really say how this API allows for accounts to be created and managed. If these accounts are just used for you (ie - the user doesn't necessarily see them), then you can mitigate some of that risk by treating the username/password as an opaque token that you manage and generate and that the user never sees.
If this is something that the user is aware of, then you'll need to approach the account linking in one of two ways:
Have them log into your service via an app or webapp using this credential info that you will need to save (ack!) and then link to the Assistant using OAuth.
Have them log into your service via an app or webapp using Google Sign-In, which will carry over to your Action. Then have them provide the credential info for the API, which you will need to save (ack!).

Create MS Teams chats with MS Graph (or PowerShell)

I'm currently trying to use Microsoft Graph to send a Microsoft Teams Chat message to a specific employee.
The idea behind that is that I want to be able to send chat messages using PowerShell, but for now, I'd be happy to get it done in Microsoft Graph first and build a PowerShell script afterward.
Important: I don't want to post a message to a Channel, only in a 1:1 chat.
What I've tried:
I'm able to get the current chats for my own user by using:
https://graph.microsoft.com/beta/users/{myid}/chats
If, however, I try that with a different user's id, I get a 401 (permission denied) error. I can't even see their current chats even though I have all available permissions.
In the error message, it says the following:
"User Id must match the API caller when called in delegated mode"
... but I don't want to use delegated mode since that'd mean I'm executing the commands as if I would be that user, and therefore couldn't create the chat message which I want in the first place.
It might sound rather confusing, so I hope you get what I mean.
To my knowledge, there's no way to send a message directly to the user without some kind of context. The problem becomes, for instance, where would the message appear, and who would it be from?
If you could deal with it being inside a Channel instead, then PowerShell is fine as you can set up a webhook to do this. I've done the same, from PS -> Teams a few years ago, so I assume it should still work. This article should help.
Alternatively, if you really want a "1-1" conversation, so to speak, you need to create and register a Bot, so that the message comes "from someone" to the user. This concept is called Pro-active Messaging and I've posted more about it here. However, coming purely from PowerShell it's going to be a LOT of work:
Create a Bot in Azure to get the App ID and Password. Technically this would be a non-existent Bot as there's no implementation, which means if the user were to reply it would go nowhere. This might be ok? You could possibly try build an Azure Function Bot in PowerShell, but not something I've done myself so can't advise (I've only used C# for Bots thus far)
Create a Conversation ID, and save it for later - again, a bunch of work.
Convert the code (e.g. from my post above) into PowerShell, referencing the relevant NuGet packages.
So, I'd recommend trying to find an approach using a Teams Channel rather, and messaging the user there, if you can manage that in your use case?
Unless all of this is irrelevant if you're trying to send on behalf of another user?
The term "Delegated" in this context refers to the type of permissions claims included in the OAuth token. There are two types; Application and Delegated.
There are two key rules when it comes to Application vs. Delegated scopes:
A single token may only contain a single type of scope. In other words, the token itself is either an Application or Delegated token, never a combination of the two.
The type of scopes applied to a Token is determined by the OAuth Grant you used to obtain it:
Authorization Code: Delegated
Implicit: Delegated
Client Credentials: Application
With regard to the List Chats (/chats) endpoint, only Delegated permissions are supported:
Delegated (work or school account): Chat.Read, Chat.ReadWrite
Delegated (personal Microsoft account): Not supported.
Application: Not supported.
There is a general rule of thumb when it comes to permissions in Microsoft Graph (I use 'general' here since there are a couple of exceptions in older endpoints): Delegated scopes that only apply to the current user end in Read or ReadWrite while those that apply to any user end in .All.
Since these two scopes (Chat.Read and Chat.ReadWrite) do not end in .All, and only Delegated scopes are supported, this tells you that the only Chats you are able to access are those owned by the currently authenticated User. In other words, you cannot read another User's chat messages via the API.
If you think about it, this makes a lot of sense. If you didn't have an authenticated User, who would the Chat message you sent be "from"? A chat message requires both a Sender and a Recipient.
For your scenario, there are a couple of possible workarounds from a Teams ChatBot to simply setting up a new User that you authenticate as and send messages to other Users from.

Microservices Service-to-Service-Communication Need-to-Know principle

Are there any best practices to minimize the exchanged data between (internal) microservices when calling the API of a service (aka Need-to-Know)?
How to achive something like this:
There are three services:
User
Notification (let's assume just email)
Shipping
When the notification service needs the email address of a user it queries the API of the user service and should get the email (and NOT the full data set).
When the shipping service needs the shipping address of a user it queries the API of the user service and should get the shipping address (and NOT the full data set).
Question:
Should this be handled inside the user service with kind of an ACL (what service "XYZ" is allowed to see)?
Using JWT for authentication, there is a need to exchange keys at all, so during the setup-phase these ACLs could be discussed between the teams.
Should this be handled inside the user service with kind of an ACL
I think this is the best option. You could delegate the actual authorization to a separate service which the User service can call with the identity of the caller and the "claim" the caller is making (eg "I am allowed to see Email Address for User"). The claims can be evaluated on a per call basis.
However, is is arguable whether you actually need to query the user service at all. It would mean a change to your design but imagine for a minute that the Notifications service already knew about the user, for example the user ID and email address, then the notifications service would not need to query anything to be able to do it's job.
In order for the notifications service to have the user data already, it is necessary for that data to have been sent to the notifications service at some point in the past. A good time to do this would be when the user is first created, or any time a user details are changed. The best way to distribute this kind of information is in the form of an event message, although you could have the distribution based on an http POST to the notifications service.