Our situation:
We have a API developed in C#/ASP.Net Core together with a separate frontend. Both the API and the frontend have an associated App Registration in Azure AD and whenever the frontend wants to make a request to the backend, it uses MSAL to obtain a token with the scopes that are exposed by the APIs app registrations.
No we want to create an extension for Azure DevOps that calls our API as well, but we are struggling with how to authenticate it. The token that you can get from the SDK is lacking our scopes because it is, as far as I understand it, only really meant to be used for DevOps internal services. I've seen this sample repository, but it seems to me that it just skips verifying the scope and the token also does not contain any user information.
The way we are doing it right now is to use MSAL inside our extension iFrames. That requires the user to sign in twice and brings a few other unwanted downsides, like missing persistence.
How would/did you go about authenticating API calls in DevOps extensions?
Related
We are using Azure AD for authentication and authorization. Our angular spa has been enabled SSO with Azure AD. We need to secure our backend
service and only allow API which has a valid jwt token.
What we have done so far is:
Registered our angular app in Azure AD.
We have configured spring microservice as a resource server and
application properties contain jwt.issuer-uri
spring.security.oauth2.resourceserver.jwt.issuer-uri=XXXXXXXXXXX-XXXXXXXXX-XXXXXXX-XXXXXXXXXXX
The issue is the token that we get from Azure AD is having an audience as "00000003-0000-0000-c000-000000000000" which means the token is generated for the Microsoft graph. I also tried accessing graph Api with this token and it worked. But what we want is to verify this token in our own spring microservice and grant permission
based on jwt provided.
To solve this issue I had to make some config changes in our Azure registered Angular app. I have added a custom scope api://<>/app and use
this scope while acquiring the token. Now the token is being validated in the backend and API working fine.
This config somehow works but doesn't seem correct to me. I am new to azure so am not sure how all things tie-up.
The new token which is now being generated has an audience as our
angular spa client Id. Is this correct? Shouldn't it be the backend
service? Any why it's getting validated by the backend with the
current configuration?
My understanding is that we don't have to register our spring
microservice with Azure Ad. I will just act as a resource server and
will decode the token provided by the angular app using the
issuer-url.
In case we need to register our backend services with azure AD then
would it be difficult to do the same for all microservices?
I have done all settings by referencing.
https://ordina-jworks.github.io/security/2020/08/18/Securing-Applications-Azure-AD.html
In some other links, I find a completely different config for setting up backend service. I am not sure which one is correct.
https://learn.microsoft.com/en-us/java/api/overview/azure/active-directory-spring-boot-starter-readme?view=azure-java-stable
Azure AD is a little confusing when following a standards based approach. I wrote a blog post on this a couple of years back:
You have already figured out that you need at least one API registration to work, to expose an API scope - so that you get usable access tokens
The generated id from the API entry in Azure then becomes your audience, as in step 9 of the article.
What we'd really like to do is this, so that we can do things like forward the JWT in microservice to microservice calls:
Get Azure AD to issue an audience claim such as api.mycompany.com that is common to all microservices
Issue multiple scopes in the access tokens, based on areas of data in microservices - as in this Curity doc
I would aim for a single entry in Azure AD to represent your platform of APIs. Then each microservice can use the same generated audience value.
Hopefully you can get multiple custom scopes to work also, though there are some annoyances here, especially when you want to use built in OpenID Connect User Info scopes, which Azure AD exposes via the Graph API.
I have a .net core api and a angular node js application that I have deployed to azure add as app services. I have registered both. I was able to successfully setup both with authentication permissions with permissions only to users within my azure domain. When anyone attempts to access either the api or the application they must login and authenticate through microsoft.
What I need now is for my app, to be able to call endpoints on my api. I want my app to have full permission so that I don't have to specify permissions on specific endpoints. I also want this to all be handled through azure, not through specific token requests in my angular code when calling the api. How can I accomplish this?
I have searched a lot of the documentation, but cannot find out how to accopmlish this. I also walked through the option of setting up explicit permissions, but I can't get that to not work either.
https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-configure-app-access-web-apis
The suggestions in the comments already cover the information you need.
I summarize it simply as below so that this post is easier to find, which can help more people.
To protect your API with Azure AD, you need to register two Azure AD apps, one is for client app and the other is for API app.
In the API app, you need to exposed API. By doing step 7 and step 8, you can expose the scope.
Then you need to configure the client app. With step 8 here, you can add the permission (scope) which is exposed by API app to the client app.
You can use MSAL to request the access token, which includes this permission (scope). You can verify it in your code. If the permission is what you expected, the client is allowed to access your API.
I have an existing API Management service that I have enabled REST APIs with. The API management services comes by default with a developer portal where people can register to use our APIs.It looks something like this.
As you can see, you can register here but also sign in. This API management service by default uses basic authentication to move you forward. After looking at the docs for API management service, I was not able to find anything that would help me replicate this so I can use APIs to make the same /register or /login calls.
My question is, how can I use my own Angular app to make API calls with a simple username/pw to allow user registration and login against API management service?
See here https://learn.microsoft.com/en-us/rest/api/apimanagement/2019-01-01/user/createorupdate for an API call to create a new User in API Management.
There are two ways to address APIM management API. The default and most commonly used way is through ARM (https://management.azure.com) this way you only will be able to use ARM auth and will go through usual RBAC checks before you're given access to any operation.
If you're aiming towards how dev portal itself uses APIM management API then you need to follow this guidance: https://learn.microsoft.com/en-us/rest/api/apimanagement/apimanagementrest/azure-api-management-rest-api-authentication. On one thing this allows you to create SAS token and call management API directly (notice that hostname in base URL is different), but more interestingly, once this API is enabled it becomes possible to call it anonymously as well. Of course only data you expose to anonymous users through dev portal is available this way.
More interestingly though is that it opens possibility to make Basic auth calls to such management API. Anonymous user could make call to any endpoint with Basic auth token based on user email and password and be authenticated this way.
I want to develop a SaaS application on Azure and deploy to the Azure marketplace. This app will be able to obtain information about the user's network. (for instance VNET information). Ideally I would like to have a single-page application that would authenticate with the user who subscribed to the app, and then make calls on a backend API tier, which would make calls to Azure management API endpoints.
The Azure docs layout a number of scenarios of how apps could interface with AD. how-to guides
I believe what im trying to do most closely matches the "Build a web app that calls web APIs" flow, which is an example of OBO. My question is, is that really describing what im doing? Is "calls web APIs" really an example of invoking APIs on the microsoft azure platform?
So my understanding is that I would develop my own API app, that would accept requests from my client browser code, which would contain an oauth token, and then the API layer would derive another token to pass onto the Azure API layer?
Im trying to keep the architecture as simple as possible, but im afraid I may be misinterpreting the Azure docs.
OBO (On-Behalf-Of) allows you to exchange an access token that your API received for an access token to another API.
The important bit is that the access token must have been acquired in the context of the user and must contain user information.
The new access token will then also contain this user's info.
So it allows your back-end API to call Azure Management APIs on behalf of the current user.
This means your API can't do anything the current user can't do.
It is limited to the user's own access rights.
The other option for authentication is to use client credentials authentication,
where your back-end API uses only a client id + certificate/secret to authenticate.
In this case the token will not contain user information.
To enable this approach, the target organization's users would have to assign RBAC access rights to your app's service principal, so it can act by itself.
You could also build a flow in your app where you setup these RBAC accesses on behalf of the current user.
Personally, I would prefer to use delegated access (OBO) whenever possible, as it will block the user from doing things they cannot do.
Though on the other hand, service principal-based access allows the organization to control your app's access better.
Scenario: I already have a registered multi-tenant web application that is compatible with Azure SSO. I'm now in the process of developing an iOS application that will support SSO authentication for the app as well.
Based on the example provided in https://azure.microsoft.com/en-us/resources/samples/active-directory-ios/ I created a Native application for the iOS app with delegated permissions from my WebApp (ref: https://stackoverflow.com/a/29810124).
This works for any user that exists within the AAD that the app was created. However, as soon as I want to SSO from a different domain that has previously authorized the WebApp I get an error:
Application with identifier 'CLIENT_ID_HERE' not found in directory DOMAIN_HERE.onmicrosoft.com
This implies that the native application is not multi-tenant? This seems a bit bizarre considering it should be possible for users outside of the domain to SSO to an application.
Right now, for my browser based SPA I'm simply able to manually call the common Azure login page to consent and get an authorization code for a user. I then send this code to a backend (the WebApp) that performs the OAuth handshake and gets a valid token. This does not require a client_secret from the application because the SPA isn't actually performing token retrieval.
So when I attempted to use the WebApp's client_id instead (similar to what https://stackoverflow.com/a/27033816 is suggesting) I was met with an error with the Azure AD iOS SDK requiring that I provided a client secret as well. It seems that the SDK is abstracting a fair amount of this and grabbing a token for you rather than performing a step when I can simply get an authorization code and send it to my WebApp.
TLDR: My requirements are very similar to the ones outlined in multiple-tenant, multiple-platform, multiple-services single sign-on using Azure Active directory where I have multiple clients (browser, iOS, Android) that all need to be able to use Azure SSO. I'm assuming the mobile apps should be able to use my existing WebApp to authenticate the users.
The question posed in the answer of the previous SO post somewhat explains my issue:
How can my mobile app access my multi-tenant web api on behalf of the user?
References
https://learn.microsoft.com/en-us/azure/active-directory/active-directory-authentication-scenarios#native-application-to-web-api
https://github.com/Azure-Samples/active-directory-dotnet-webapi-multitenant-windows-store
At present the native app which register on the Azure portal doesn't support multi-tenant. You may consider using the V2.0 endpoint which also support the Microsoft accounts.
TLDR: My requirements are very similar to the ones outlined in multiple-tenant, multiple-platform, multiple-services single sign-on using Azure Active directory where I have multiple clients (browser, iOS, Android) that all need to be able to use Azure SSO. I'm assuming the mobile apps should be able to use my existing WebApp to authenticate the users.
Did you mean that have different font-end and the Multi-Tenant Web Application is the back-end? In this scenario, there is no need to register another native client application on the portal, you can refer here about add authentication for the iOS app.
So the majority of Microsoft's tutorials use their AAD SDK to generate OAuth access tokens whereas I needed to simply get an authorization_code to send up to a backend that's registered as an existing multi-tenant web application so it could properly generate a token using its own client_id.
This was done using the correct redirect_uri in the AD OAuth code documentation:
For native & mobile apps, you should use the default value of urn:ietf:wg:oauth:2.0:oob
Note that sending up urn:ietf:wg:oauth:2.0:oob will actually result in a schema error for the multi-tenant OAuth login page (https://login.windows.net/common/oauth2/authorize) so you must use https://login.microsoftonline.com/common/oauth2/nativeclient instead.