Azure static web app generated envs and azure AD tenant reply urls - azure

We have an azure static web app with authentication provided by azure active directory (company tenant)
This works for production but when we open a PR and get a staging url generated it appends an identifier e.g. https://salmon-mountain-xxxxxxx-20.azurestaticapps.net
Obviously this isn't set as a reply/redirect url in the app registration so auth fails.
The site is currently on the public internet but only organisation AD accounts can log in. Is my only option adding a wildcard in the manifest? I know wildcards aren't generally recommended and this functionality may vanish in the future

• You have the option of adding a user to a role, generate invitations to associate specific users to a specific role through the azure portal by adding a comma separated list of the role names to be assigned. These can be defined in staticwebapp.config.json.file and this file can be located in ‘app_location’ in the workflow file of the app build.
• Once the external users for whom the app to be accessed are invited, you now must check the route rules for any change in the authentication process. Routes are secured by adding one or more role names into a rule's allowedRoles array. By default, every user belongs to the built-in anonymous role, and all logged-in users are members of the authenticated role. Optionally, users are associated to custom roles via invitations. For instance, to restrict a route to only authenticated users, add the built-in authenticated role to the allowedRoles array as below: -
{
"route": "/profile",
"allowedRoles": ["authenticated"]
}
• Also, check the response overrides that are configured for your static web app. They should be as follows: -
{
"responseOverrides": {
"400": {
"rewrite": "/invalid-invitation-error.html"
},
"401": {
"statusCode": 302,
"redirect": "/login"
},
"403": {
"rewrite": "/custom-forbidden-page.html"
},
"404": {
"rewrite": "/custom-404.html"
}
}
}
• Also, check the networking section to control the network configuration of your static web app. It has details of all the IP addresses that are allowed to access your app.
Please check the below link for more information on configuring the app files of your static web app for options on configuring other than wildcard details in the app manifest file: -
https://learn.microsoft.com/en-us/azure/static-web-apps/configuration#example-configuration-file
https://learn.microsoft.com/en-us/azure/static-web-apps/authentication-authorization

Related

Configuring an Azure Static Web App to authenticate using Azure AD B2C

I've built a basic Vue web app using Azure Static Web Apps, and I'm trying to configure custom authentication. I've already managed to get everything (mostly) working using Auth0 by following the documentation and referencing this handy blog post.
For Auth0, I added AUTH0_ID=<my-auth0-id> and AUTH0_SECRET=<my-auth0-secret> to the local.settings.json file. My staticwebapp.config.json looked like this:
...
"auth": {
"identityProviders": {
"customOpenIdConnectProviders": {
"auth0": {
"registration": {
"clientIdSettingName": "AUTH0_ID",
"clientCredential": {
"clientSecretSettingName": "AUTH0_SECRET"
},
"openIdConnectConfiguration": {
"wellKnownOpenIdConfiguration": "https://<my-auth0-tenant>/.well-known/openid-configuration"
}
},
"login": {
"nameClaimType": "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
"scopes": ["openid", "profile"]
}
}
}
}
}
I'm now trying to set up authentication using Azure AD B2C. My understanding is that Azure Static Web Apps handles a portion of the authentication such that I should configure the ID provider to work with a web app rather than with a single page app framework. This is what I did when using Auth0 and it seemed to work.
I've added AADB2C_ID=<my-azure-ad-b2c-id> and AADB2C_SECRET=<my-azure-ad-b2c-secret> to the local.settings.json file. In staticwebapp.config.json I replaced ClientIdSettingName to AADB2C_ID, clientSecretSettingName to AADB2C_SECRET, and wellKnownOpenIdConfiguration to https://<my-azure-ad-b2>.b2clogin.com/<my-azure-ad-b2c>.onmicrosoft.com/v2.0/.well-known/openid-configuration?p=B2C_1_signupsignin1. This references the 'signupsignin' user flow on my B2C tenant.
At this point I can visit /login which points to /.auth/login/aadb2c, initiates the user flow, and lets me sign up and verify as expected. The test user is then created in my Azure AD B2C tenant. However, B2C then tries to redirect me to /.auth/complete which throws a 403 error:
We need an email address or a handle from your login service. To use
this login, please update your account with the missing info.
I've tried adding /.auth/complete as an allowed redirect URI in Azure AD B2C but this doesn't fix things. What am I missing here?
Try changing to this: "nameClaimType": "emails".
Sourced from staticwebapp.config.json in here: https://github.com/Azure/static-web-apps/issues/457

Azure AD App Registration limits Redirect URIs to 256

Is it possible to use a single Redirect URI for multiple tenants and multiple web applications using a single Azure AD App Registration?
I have reached the limit of 256 URIs in my Azure multi tenant App Registration where each registered tenant have their own set of redirect URIs.
The redirect URIs follow this pattern
http://example.com/consumer1/webapp1/signin-oidc
http://example.com/consumer1/webapp2/signin-oidc
http://example.com/consumer2/webapp1/signin-oidc
http://example.com/consumer2/webapp2/signin-oidc
After reading Use a state parameter I had the idea to create a new web app that only authenticates and then redirects the user to the originally requested URI. But it is not possible to configure the OpenId CallbackPath to the new auth/authorize/redirect app.
How should I solve this?
ASP.NET Core
authenticationBuilder.Services.AddSingleton<IConfigureOptions<OpenIdConnectOptions>, ConfigureAzureOptions>();
authenticationBuilder.AddOpenIdConnect();
private class ConfigureAzureOptions : IConfigureNamedOptions<OpenIdConnectOptions>
{
public void Configure( string name, OpenIdConnectOptions options )
{
options.ClientId = "555-xxx";
options.Authority = "https://login.microsoftonline.com/common";
options.CallbackPath = "https://mydomain/myauth-redir-app/signin-iodc" // this is not allowed
options.Events = new OpenIdConnectEvents
{
OnRedirectToIdentityProvider = ctx =>
{
// remember the URL the user requested, to be picked upp later after AAD auth
ctx.ProtocolMessage.SetParameter("state", "set_org_url");
}
OnTokenValidated = ctx =>
{
// this code should run in myauth-redir-app and pick up the state
// and redirect the user to the originally requested URL
var stateValue = ctx.ProtocolMessage.GetParameter("state");
}
}
}
}
Rejected solutions
Using wildcards in the URI is no longer supported
Creating an App Registration for each Web Application still limits me to 256 tenants, which is too few.
Creating new App Registrations for each tenant is too cumbersome to maintain and configure.
I do not want to register the Redirect URI in the tenants Service Principal, I must be able to add and remove URIs without the customer having to take action.
It's the protocol limitation not an Azure AD issue, please check: https://stackoverflow.com/a/812962/1384539
To solve this, you need to redirect to an intermediate page which will handle the right place to redirect your user. As far as I know, there's no other way.
Did that make your registration multi-tenant by finding the Supported account types switch on the Authentication pane of your application registration in the Azure portal and setting it to Accounts in any organizational directory ?
With multi-tenant application you just need one redirect url( the original one) . For a multi-tenant application, the initial registration for the application lives in the Azure AD tenant used by the developer. When a user from a different tenant signs in to the application for the first time, Azure AD asks them to consent to the permissions requested by the application. If they consent, then a representation of the application called a service principal is created in the user’s tenant, and sign-in can continue. A delegation is also created in the directory that records the user’s consent to the application.
See document : https://learn.microsoft.com/en-us/azure/active-directory/develop/howto-convert-app-to-be-multi-tenant#update-registration-to-be-multi-tenant

Allowing public access to only 1 endpoint of Azure Application

I'm building a small Azure Serverless Application with 3 distinct functions triggered by 3 different HTTP events. I set the "Authorization Level" to "Anonymous" for each of the functions. Then I set up the Authentication (on the application level) to link to my Azure Active Directory. Although it took me some time to figure out that part, in the end it appears to work like a charm. The issue is that right now I'm required to pass the bearer token for each and every one of these functions, whereas I need one of them to be publicly accessible.
Is there any way to do that that does not require me to split that one function into a separate Azure Application?
I think URL authorization rules should help here.
For your scenario, Enable the Authentication/Authorization and allow anonymous access in the portal. Next, you'll want to create an authorization.json file in the root of your site and define two routes:
Disable anonymous access at the root.
Enable anonymous access for the anonymous function URL.
authorization.json
{
"routes": [{
"path_prefix": "/",
"policies": { "unauthenticated_action": "RedirectToLoginPage" }
},{
"path_prefix": "/api/HttpTrigger1",
"policies": { "unauthenticated_action": "AllowAnonymous" }
}]
}
NOTE: Make sure to Stop/Start Function App after enabling the Authentication/Authorization and adding the authorization.json file at wwwroot folder.
Not sure how you implemented the app level security but in a regular OWIN or CORE app, the token handler will just pass the request as unauthenticated to the controller method if it does not find a valid token in the Authorization header (no header or token invalid). It's up to the method then to decide whether to handle the request or reject as unauthorized. Can you change your token verifier accordingly? (In fact, if your API can receive tokens issued by different issuers - AAD, B2C, Ping - you can configure several token handlers, each will try to va

Azure AD remove permissions for registered app

I am using Azure AD to secure my service to service calls. (Each service having an application identity in Azure AD).
Example: Application A wants to access Application B.
I noticed that when requesting an accesstoken from Application A using Client Credential Flow (with Certificate), an accesstoken is issued without having me to explicitly set the permissions to access Application B.
This seems odd to me because the token returned has its audience set to Application B even thought I haven't explicitly given it access.
If I understand correctly, all registered app have access to each other by default?
Is there a way in Azure AD to explicitly require permissions to be set in order for application to access each other?
Below is a screenshot of Application A required permissions. As you can see, Application B is not listed here.
In the following screenshot, I assigned TodoListService (aka Application B) to the required permissions of Application A
I noticed that when requesting an accesstoken from Application A using Client Credential Flow (with Certificate), an accesstoken is issued without having me to explicitly set the permissions to access Application B.
Yeah, that one can be a bit surprising and I'm not sure why that is the case either.
What you need to do is define application permissions on the API, and then assign it on the client.
Then you need to check the caller has the required app permission in the token.
I have an article on this topic: Defining permission scopes and roles offered by an app in Azure AD.
To define an app permission on the API, you'll have to edit its manifest in Azure AD, and add an app role with member type of Application, something like:
{
"appRoles": [
{
"allowedMemberTypes": [
"Application"
],
"displayName": "Read all todo items",
"id": "f8d39977-e31e-460b-b92c-9bef51d14f98",
"isEnabled": true,
"description": "Allow the application to read all todo items as itself.",
"value": "Todo.Read.All"
}
]
}
IIRC you have to generate a GUID for the id.
After defining this permission on the API, go to your client app, and add the app permission in the Required permissions.
Then you should press Grant permissions to grant the app permission.
Now then when the client acquires a token with client credentials, the token will contain:
{
"roles": [
"Todo.Read.All"
]
}
So you'll have to check that that is present.

Azure AD - Check for security group membership - (Node.js, passport, Azure Web App)

We are trying to set up an authentication/authorization-process with the following requirements:
Authentication: Done by Azure AD.
Authorization: Only members of a specific security groups should be allowed to access the app.
While the authentication part seems to work without problems, we are stuck at the authorization part. We are using Express and Passport.
Azure AD some tokens to req.headers, e.g.
x-ms-token-aad-access-token
x-ms-token-aad-refresh-token
x-ms-token-aad-id-token
We are currently using the id-token together with the passport-azure-ad BearerStrategy to check the security groups of the user against the allowed security groups.
The problem is: As soon as the id-token expires, the application won't let us access the app. Assuming setting {session: true} in passport could solve this issue, we enabled the session, but no luck.
Doing some more research I found this post: How to refresh an ID Token from Azure AD in a Web App?, which states that only access-tokens can be refreshed, but ID tokens cannot and should not.
Examining the x-ms-token-aad-access-token and the x-ms-token-aad-refresh-token, we found that they don't have the JWT-structure, e.g
eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiIsIng1dCI6Ik5HVEZ2ZEstZnl0aEV1THdqcHdBSk9NOW4tQSJ9.eyJhdWQiOiJodHRwczovL3NlcnZpY2UuY29udG9zby5jb20vIiwiaXNzIjoiaHR0cHM6Ly9zdHMud2luZG93cy5uZXQvN2ZlODE0NDctZGE1Ny00Mzg1LWJlY2ItNmRlNTdmMjE0NzdlLyIsImlhdCI6MTM4ODQ0MDg2MywibmJmIjoxMzg4NDQwODYzLCJleHAiOjEzODg0NDQ3NjMsInZlciI6IjEuMCIsInRpZCI6IjdmZTgxNDQ3LWRhNTctNDM4NS1iZWNiLTZkZTU3ZjIxNDc3ZSIsIm9pZCI6IjY4Mzg5YWUyLTYyZmEtNGIxOC05MWZlLTUzZGQxMDlkNzRmNSIsInVwbiI6ImZyYW5rbUBjb250b3NvLmNvbSIsInVuaXF1ZV9uYW1lIjoiZnJhbmttQGNvbnRvc28uY29tIiwic3ViIjoiZGVOcUlqOUlPRTlQV0pXYkhzZnRYdDJFYWJQVmwwQ2o4UUFtZWZSTFY5OCIsImZhbWlseV9uYW1lIjoiTWlsbGVyIiwiZ2l2ZW5fbmFtZSI6IkZyYW5rIiwiYXBwaWQiOiIyZDRkMTFhMi1mODE0LTQ2YTctODkwYS0yNzRhNzJhNzMwOWUiLCJhcHBpZGFjciI6IjAiLCJzY3AiOiJ1c2VyX2ltcGVyc29uYXRpb24iLCJhY3IiOiIxIn0.JZw8jC0gptZxVC-7l5sFkdnJgP3_tRjeQEPgUn28XctVe3QqmheLZw7QVZDPCyGycDWBaqy7FLpSekET_BftDkewRhyHk9FW_KeEz0ch2c3i08NGNDbr6XYGVayNuSesYk5Aw_p3ICRlUV1bqEwk-Jkzs9EEkQg4hbefqJS6yS1HoV_2EsEhpd_wCQpxK89WPs3hLYZETRJtG5kvCCEOvSHXmDE6eTHGTnEgsIk--UlPe275Dvou4gEAwLofhLDQbMSjnlV5VLsjimNBVcSRFShoxmQwBJR_b2011Y5IuD6St5zPnzruBbZYkGNurQK63TJPWmRd3mbJsGM0mf3CUQ
They don't contain any dots and thus don't pass the JWT-verification.
Resulting in the following question:
What is the correct way to check security groups of a user against specified allowed security groups?
You can do it through passport in one call, you do not need to do extra calls to other api layers, as seams to be suggested in multiple posts online. Using the v2 endpoint and defining a scope you can choose what you have access to and what you receive back in the token. Some options, including security group do require you to modify the manifest, see below.
In your Azure Active Directory go to the App registration you are using the authenticate users. In the manifest for that app registration change the groupMembershipClaims from null to "SecurityGroup" or "All" if want to include office groups etc.
{
"id": "some-id",
"accessTokenAcceptedVersion": null,
"allowPublicClient": false,
"appId": "some-id",
"appRoles": [],
"oauth2AllowUrlPathMatching": false,
"createdDateTime": "2018-11-15T17:49:23Z",
"groupMembershipClaims": "SecurityGroup",
"identifierUris": [ ...............
It then populates the Groups field with an array of the groups using their Object ID.
So you can get the array at req.user._json.groups
if (req.user._json.groups.indexOf('some-group-Object-ID') > -1) {
//In Group
} else {
//Not in Group
}
Apart from checking group claims in ID token , you could also call microsoft graph api to get the groups that the user is a direct member of :
POST https://graph.microsoft.com/beta/me/getMemberGroups
Content-type: application/json
Content-length: 33
{
"securityEnabledOnly": true
}
Or using Auzre AD Graph api :
POST https://graph.windows.net/myorganization/{resource_collection}/{resource_id}/getMemberGroups?api-version
Content-Type: application/json
{
"securityEnabledOnly": false
}
For how an App Service Web, Mobile, or API app can be configured to call the Azure Active Directory Graph API on behalf of the logged-in user. You could refer to below document which show detail steps:
https://cgillum.tech/2016/03/25/app-service-auth-aad-graph-api/
After authentication, access token can be fetched directly from a built-in request header (x-ms-token-aad-access-token) and you could make a http request to call graph api to get the group information .

Resources