Acquire multiple scopes at once - ASP.NET Core MVC - asp.net-authorization

I'm building an ASP.NET Core 6 MVC app and using the Microsoft.Identity.Web package for authentication and authorization.
How can my application acquire multiple scopes at once when a user from a new tenant logs in for the first time?
My app will be multi-tenant, and I want to acquire multiple scopes when a user from a new tenant logs in. I want to acquire the scopes up front (and not incrementally) because a frequent use case is that:
An admin user from a new tenant logs in and grants consent for the required scopes on behalf of their organisation
A non-admin user from the same tenant logs in afterwards. This user is not allowed to grant consent, and thus relies on the admin user to have granted consent up front.
I was initially using the [AuthorizeForScopes] attribute on my home controller to ensure that the relevant scopes were acquired. This works fine when acquiring a single scope at a time, but when I attempt to acquire multiple scopes at once it seems like the client (browser) goes into and endless loop. It's like it doesn't know which scope to ask for first.
I was expecting that my application would simply ask the user to grant consent to all the specified scopes at once.
Specifically I'm asking for these scopes:
https://graph.microsoft.com/v1.0/user.read
https://management.core.windows.net/user_impersonation
https://database.windows.net/user_impersonation

Related

Sending automated emails using Gmail API with Java and Oauth authentication

I have a web app which sends emails (gmail) in name of my users
When a user registers, she supplies gmail account and password. Also she has to enable access for Less Secure Apps (I recommend to create a new account for this)
Then I can open a gmail session
session = Session.getInstance(props, new javax.mail.Authenticator() {
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(user.getEmail(), user.getPassword());
}
});
and send emails on her behalf.
Unfortunately this is going to stop working next 30th May, when Google will allow only OAUTH2 access
I have followed Java Quickstart for Gmail API and I have code up and running for sending emails with OAUTH2: enable gmail api, create an application on google cloud platform, grant send permission, oauth2 client id credential created...
The problem I have is I can't see a way to automatize this task because when creating an authorized credential, a consent screen displays on browser and you have to select the account to be granted manually (maybe because my app in google cloud platform is still pending to be reviewed)
Is there a way to infer the gmail account you want to access from the credentials file (client_secret.json)? Is there a way to automatize this?
No, or yes. It depends.
The whole point of OAuth2 is to improve security by working with authorization tokens rather than asking for user credentials. To do this the user has to consent to the app's access request, and thus the OAuth consent screen cannot be bypassed. This is
explained in Google's documentation. It's not related to your app's review status but rather it's the way OAuth works.
You can still work in a similar way, though . Instead of asking for username and password upon the user's registration you can redirect them to the OAuth consent screen so they can authorize your app. Make sure that your app is requesting offline access type and then you can retrieve an access_token and a refresh_token. These will essentially work as your credentials and you can use the refresh token to generate new access tokens when needed without having the user go through the consent screen each time.
The refresh token doesn't have a "natural" expiration so you can keep using it indefinitely, but there are a few scenarios where it will become invalid, such as it not being used for six months, the user changing passwords (if using Gmail scopes), the user manually revoking access, etc. In these cases you will need to direct them to the consent screen again to reauthorize your app.
In this sense, your app can still work automatically without user input except the initial setup, which you already had to deal with when they supplied you with their credentials. The refresh token expiration can even be compared to what you had to do when the users changed their passwords in your current workflow.
One exception to this are service accounts. If you and your users are part of a Google Workspace domain you can delegate domain-wide access to it, then the service account will be able to access user data without any manual input. Of course, this is because as the domain administrator you pretty much own all the accounts under it. But if you're working with a publicly available application you will have to deal with the limitations I mentioned above.
Sources:
Google's auth overview
Using OAuth 2.0 to access Google APIs
OAuth 2.0 for web applications
The OAuth consent screen

Reading the emails of all users using Microsoft Graph API by creating an app with Application Level permissions

I'm trying to create an app within the Azure app management portal that will serve as a template to be used with any tenant. Basically what we are trying to do, is create a connector that will be approved using admin consent, and receive application level permissions to read all the emails in the organization using Graph API.
What I have managed to do so far is create an app within our own tenant and get application level permissions for this tenant only. This enabled me to successfully read all emails in my organization only (which is not possible using delegated permissions).
What is the right way to receive application level permissions for any tenant, using admin consent? Is the only way to do it, for the specific tenant to manually add an application that will receive admin consent?
I am using django with the social_core module.
Something does not add up...
Thanks.
You can register a single application (with a single client ID and set of credentials that you control), configure the permissions you desire/require, and then customers from different tenants can each grant admin consent for your application, in their own tenant.
If your application/service does not have a sign-in experience (i.e. it is exclusively used as a background service and users never sign in to it), you can construct the admin consent URL, such as:
https://login.microsoftonline.com/organizations/v2.0/adminconsent
?client_id={client_id}&scope=.default&redirect_uri={your_redirect_url}
You can read more about the admin consent endpoint at: https://learn.microsoft.com/azure/active-directory/develop/v2-admin-consent

Authorization and microservices

Our system is moving from a monolithic to a microservice architecture.
The microservice architecture comes with technical challenges that we need to address and one of them is AuthN/AuthZ.
Our approach is to have an authentication service that would authenticate users and generate access/refresh tokens (JWTs).
Access tokens would then be passed in request header through the chain of microservices such that each microservice just have to validate the token to determine the user has been successfully authenticated.
For the AuthZ part, permission enforcement is done in the microservice itself. My questions are related to AuthZ.
To illustrate the talk, let’s take a specific example of a receptionist who wants to register a new member to his fidelity program, for instance from a Web application.
To support this use case, let’s assume the system has 2 microservices, the ReceptionService and the MemberService.
The ReceptionService offers one REST API to initiate the member registration flow. It requires user permission “registration” to allow execution.
The MemberService offers one REST API to create a new member resource which is protected by CRUD permissions.
A request flow would be:
The web application, on which the user has previously logged in, sends a member registration request to the ReceptionService API including the user access token in the header.
The ReceptionService validates the user token, ensures user is granted with permission “registration”, does whatever business logic it needs to do, and finally sends a member creation request to the MemberService API including the user access token in the header.
The MemberService validates the user token, ensures user is granted with permission “member.create”, and finally creates the member.
To design a solution for such case, my team worked on the following assumptions/prerequisites:
A microservice must always enforce permission (at least for significant API operation such as creating a member). Thus the CRUD permissions on the MemberService in the example above even if Products Managers might only require the top-level “registration” permission.
A user who is able to start a use case because it has the “top-level”
permission must be able to complete it. Meaning It shall not get
errors because he is lacking another permission from somewhere in the
underlying services’ call chain.
Admin users shall not have to understand the chain of permissions
that is required to perform a use case. In our example, Admins should
be able to provide users only with the “registration” permission.
To be able to complete the above example, there are 2 different permissions to be assigned to the user, which breaks some of our assumptions/prerequisites. To overcome that, one of my colleague proposed to consider declaring microservices as identities/users in our AuthN system so that they could be assigned with the appropriate permissions. The user token initially provided would then be replaced by participating services token among the call chain.
To come back to the example, the new request flow would be:
The web application, on which the user has previously logged in,
sends a member registration request to the ReceptionService API
including the user access token in the header.
The ReceptionService validates the user token, ensures user is
granted with permission “registration”, does whatever business logic
it needs to do, and finally sends a member creation request to the
MemberService API including its own service token in the header (and
so replacing the original user token).
The MemberService validates the service token, ensures service is
granted with permission “member.create”, and finally creates the
member.
With this solution, service’s identities in the AuthN system would be flagged in a way that they are filtered from an Admin user managing permission assignments. Permission assignments to services identities would be pre-defined with no possibility for a user to configure it. While it fulfills our assumptions/pre-requisites, I have few concerns about this approach:
When dealing with the “who did what” (audit), user identity and
service identity provided in the tokens would be listed
indifferently. In our example, the RegistrationService would audit
the actual user who initiated the operation but the MemberService
would audit that the operation was performed by the
“RegistrationService”. In reporting scenarios, it means I would need
to reconciliate audit from both systems to determine “who actually
did create the member” using somehow a correlation ID.
While I understand the need to create an identity for a system
component in scenarios which do not involve an actual user (automated
batch/third party access ..), I am not comfortable with replacing the
user token with a service token in scenarios where a user actually
initiated the use case. Is that a standard design pattern?
Could it be that some of our assumptions/prerequisites just wrong?
For instance, is it really a security hole that some microservices do
not enforce permission even if they are only accessed by others
controlled microservices in a safe environment? Assuming the answer
to the latter is “no, it would not be a security hole”, then what if
tomorrow, I need to make the MemberService API also accessible
outside of the safe environment (for instance, because I make it
available to a third party). I would most likely need to add a
permission on it, which would break my registration flow.
Is it wrong to say we do want Admin users to know which set of
permissions are required for a use case and that we should rather
build the system so it gracefully handles failures due to lack of one
permission in the call chain (maybe using Sagas and compensation
routines)?
Any comment or links to resources would be greatly appreciated.
Thanks!
Each service should own it's own permission-schema, but I would recommend you using Service Mesh to not Authenticate user throughout each hop/Microservice.

Laravel Passport - Access token without user

I have a Mobile application which uses oauth for authenticating users into the the app and getting/posting data to the API.
Currently I am using password grant types, which relies on a user entering their username & password. This is fine for carrying out tasks that the user needs to be authenticated for, however, the application itself needs to carry out duties that are not related to the application itself but only this application can be granted access.
What I therefore wondering - Is it possible to create a client which does not require a username/password in order to be given an access token so that the tasks (reading / writing) data can be done once authenticated? The access token can be granted for a long period of time and we are also implementing a way to refresh the token so the application can communicate with certain aspects of the API.

Using Spring SAML Extension implementing identity federation

We are trying to use Spring SAML Extension to implement identity federation which is a use case described in Security Assertion Markup Language (SAML) V2.0 Technical Overview (5.4.3 Federation Using Persistent Pseudonym Identifiers).
Our application try to associate remote users with local accounts(in out app) for SSO between business partners. Our application is a SP and partner's application is a IDP.
In this scenario, if a user attempt to access secure resource and does not have logon session on our app, the SP will redirect user to IDP. After user is authenticated at IDP site, a HTTP request will send to SP Assertion Consumer Service with a name identifier. At SP site, if the name identifier was not mapped to a local account, our app will present a login page to challenge user to provide local identity of our app. After user provider valid credential then a local session is created and user can access secure resource. Also a federation of two account (SP and IDP) is created and persisted.
I have searched many examples but have not found a configuration that clearly describes what I need. I have not found a Spring document that describes how I can implement this.
Basically, my questions are how to create/config custom login screens and persist this identity federation. Any thoughts, examples or documents?
btw, this is very similar to Account Linking in Ping federation.
Thanks for any help, much appreciated.
One approach to go about it is to:
implement a custom SAMLUserDetailsService which maps content of the Assertion (persistent NameID) to the local account
in case the local account exists it populates e.g. a UserDetails object with user's data and adds a GrantedAuthority e.g. ROLE_FULL_ACCESS
otherwise it returns an object which indicates that local account is missing, but doesn't throw an exception
implement a custom AuthenticationSuccessHandler which detects whether user has a local account (based on the Authentication object with data populated from the SAMLUserDetailsService)
in case user has a local account continue to the default page
otherwise redirect user to page with challenge for linking of the local identity
implement e.g. an MVC Controller, or another Spring Security authentication endpoint which accepts callback from the local identity linking page (with user's credentials to the local account)
store the link between persistent ID and local account
update the current Authentication object with the new UserDetails object reflecting the selected local account
redirect user to the default page
Content which should be available only to fully authenticated users (i.e. users with local account) should be secured with role ROLE_FULL_ACCESS, so it cannot be accessed by users who authenticated using the IDP, but who haven't performed the linking yet.

Resources