How to configure .NET 7 Web API for deploying to Azure App service - azure-active-directory

I created a Azure .NET 7 sample Web API and wanted to publish it to my Azure App service - configured, then selected Publish button in Visual Studio and after a while I've got success information in Output window.
After that, browser is opened with my site's address but it returns not found 404 error
I have added Microsoft Identity platform (previously Azure AD) - maybe that somehow affects this, but I am using same Azure AD for my other Azure API without issues.
When I run locally this API is started and page is opened in browser successfully.
content of appsettings.json
{
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"Domain": "....onmicrosoft.com",
"TenantId": "...",
"ClientId": "...",
"CallbackPath": "/signin-oidc",
"Scopes": "access_as_user"
},
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"MicrosoftGraph": {
"BaseUrl": "https://graph.microsoft.com/v1.0",
"Scopes": "user.read"
}
}
I followed steps in Visual Studio Web API creation wizard
In publish window connection validates successfully
Also checked this quickstart guide - didn't notice anything that I might have done wrong, but it's for .NET 6, not .NET 7, so maybe .NET 7 need to do something differently
It should redirect to https://login.microsoftonline.com/... for authorization, but it just returns not found
From this stackoverflow post found out that I need to manually create a web.config for my API, got this far with creating it, but seems like still missing something
<?xml version="1.0" encoding="utf-8"?> <configuration> <location path="." inheritInChildApplications="false"> <system.webServer> <handlers> <add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" /> </handlers> <aspNetCore processPath="dotnet" arguments=".\MyWebApp.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="InProcess" /> </system.webServer> <system.web> <httpRuntime targetFramework="net6.0" /> </system.web> </location> </configuration>
Update
Turns out it is not working also locally - when trying out endpoint through swagger it returns 401 www-authenticate bearer
Update2
When I created Web API I selected to use Microsoft Identity platform and this code was generated. Do I need to configure AddJwtBearer here?
builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApi(builder.Configuration.GetSection("AzureAd")) .EnableTokenAcquisitionToCallDownstreamApi() .AddMicrosoftGraph(builder.Configuration.GetSection("MicrosoftGraph")) .AddInMemoryTokenCaches();

When we create the Web API project, and run it locally, it will redirect to he Swagger UI to list all the APIs and help test the api, but it doesn't mean the Swagger page is the default website, it will only appear when in the development environment, after publishing to Azure web app, the API home page will be xx.azurewebsite.net but there's no API or View bind to this route, so a 404 error indicating that there's no API in the application which the routing is xx.azurewebsite.net. And normally, the API routing should look like xx.azurewebsite.net/api/controller/xx
If you want your web API to be protected by Azure AD, you can take a look at this document. To summarize here, you need to add Cors policy and add Azure ad authentication into Program.cs.
using Microsoft.Identity.Web;
builder.Services.AddCors(options =>
{
options.AddPolicy(name: "mypolicy",
policy =>
{
policy.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod();
});
});
builder.Services.AddMicrosoftIdentityWebApiAuthentication(builder.Configuration);
...
app.UseCors("mypolicy");
app.UseAuthentication();
app.UseAuthorization();
Then here it used some configuration, you need to add configuration in appsettings.json. The value of the properties you can follow the document to create Azure AD resource and get them.
"AzureAd": {
"Instance": "https://login.microsoftonline.com/",
"ClientId": "azure_ad_app_id",
"ClientSecret": "client_secret",
"Domain": "tenant_id",
"TenantId": "tenant_id"
//I used the same azure application which exposed api and add api permission,so I can comment this line
//"Audience": "api://azure_ad_app_id_which_exposed_api"
},
Finally, in the Controller, add [Authorize] before the controller. Then the api now is protected by Azure AD, you have to have a correct access token to visit it.
Assume you are exposing a delegate API permission. Then the api permission you assigned to your Azure AD application should look like api://azure_ad_app_id_exposed_api/permission_name_you_defined. Then you can use following link to use auth code flow to generate access token.
https://login.microsoftonline.com/tenant_id/oauth2/v2.0/authorize?
client_id=azure_ad_app_id
&response_type=code
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&response_mode=query
&scope=profile email openid offline_access
&state=12345
Visiting the URL above will ask you to sign in with your microsoft account, after sign in successfully, you will see URL in the browser like copy the value of the code, you need to use it next.
http://localhost/myapp/?
code=0.ASxxx
&state=12345&session_state=c71be61a-c4cc-4624-9fa4-fe6c4b2d6b88
Then use the request like below to generate the access token:
Post: https://login.microsoftonline.com/tenant_id/oauth2/v2.0/token
Content-Type: application/x-www-form-urlencoded
client_id=azure_ad_app_id
&scope=api://azure_ad_app_id_exposed_api/api_name
&code=O.xxxx
&redirect_uri=http%3A%2F%2Flocalhost%2Fmyapp%2F
&grant_type=authorization_code
&client_secret=client_secret

Related

.mem and .wasm MIME type errors in Azure only

This app was built in Visual Studio 2022 using the "ASP.NET Core with React.js" project template. In a nutshell this template sets up a React front-end that lives in the same project with a .NET6 Web API backend. A proxy config file defines routes that will be sent to the API, all others default to the React app. It's a clever setup and is working well except for one recent problem.
When I run the app locally at localhost:3000 everything works flawlessly.
I created a publish profile in VS2022 to publish directly to Azure as an app service. The publish is always successful. I can browse the app in Azure and the React UI loads without issues. There is one button in the app that triggers a 3rd party library called PDFTron to load an Excel file and preview it in the page. Running locally this works perfectly. Running in Azure I get a series of errors and the Excel preview never loads:
I'm using a 3rd party library called PDFTron for displaying an Excel file in the page.
Things I've tried:
PDFTron has an article listing the MIME types that need to be enabled. Since I'm haivng no problem running locally I assume they're already enabled by default in my local VS2022 environment. In azure I manually edited the published web.config as follows:
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\DocuParseWebApp.dll" stdoutLogEnabled="false" stdoutLogFile="\\?\%home%\LogFiles\stdout" hostingModel="inprocess" />
<staticContent>
<mimeMap fileExtension=".xod" mimeType="application/octet-stream" />
<mimeMap fileExtension=".res" mimeType="application/octet-stream" />
<mimeMap fileExtension=".mem" mimeType="application/octet-stream" />
<mimeMap fileExtension=".wasm" mimeType="application/application/wasm" />
</staticContent>
</system.webServer>
Unfortunately this had no effect.
My Program.cs file:
var builder = WebApplication.CreateBuilder(args);
// Add services to the container.
builder.Services.AddControllers();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.MapControllerRoute(
name: "default",
pattern: "{controller}/{action=Index}/{id?}");
app.MapFallbackToFile("index.html"); ;
app.Run();
Are there any additional steps to configure an App Service in Azure to work with these MIME types?

React page not rendering when using Okta

I working on React app which is secured by Okta OAuth provider. Currently, all of my routes are authenticated. I want a public route where anyone can access it. Eg: https://my.example.com/welcome
These are the configs that I have used
application.yml
okta:
oauth2:
issuer: https://xxxxxxxxx.okta.com/oauth2/default
clientId: xxxxxxxxxxxxxx
clientSecret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
post-logout-redirect-uri: /
redirect-uri: /login/callback
Spring security config
httpSecurity.authorizeRequests()
.antMatchers("/", "/welcome").permitAll()
.anyRequest().authenticated()
.and().logout().logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.and().oauth2Client()
.and().oauth2Login();
return httpSecurity.build();
React Route
<Route path={"/welcome"} exact={true} render={(props) => (<WelcomePage/>)}/>
When I visit /welcome route I'm getting a blank page with this warning message in the browser
Cross-Origin Read Blocking (CORB) blocked cross-origin response https://xxxxxxx.okta.com/oauth2/default/v1/authorize?response_type=code&client_id=xxxxxxxxx&scope=profile%20email%20openid&state=rDYLqV7WDv2la1onSvQsTNeXCvDmWhS0_ZoPFlMAE80%3D&redirect_uri=https://xxxxxx.xxxxx.com/careportal/login/callback&nonce=XvMoC5iP5OGYsvG0bS-QfQh1yfYmhNohmD7GvfukyCo with MIME type text/html. See https://www.chromestatus.com/feature/5629709824032768 for more details.
Can anyone help me to access a public route without auth?
TIA
If you have anything else than spring-boot-starter-oauth2-resource-server as OAuth2 lib in your Spring project, remove it and configure your Spring REST API as a resource-server.
With the helper lib from second tutorial, this might be enough:
<dependency>
<groupId>com.c4-soft.springaddons</groupId>
<!-- replace "webmvc" with "weblux" for reactive app -->
<!-- replace "jwt" with "introspecting" if Okta access-tokens are not JWTs -->
<artifactId>spring-addons-webmvc-jwt-resource-server</artifactId>
<version>6.0.4</version>
</dependency>
#EnableMethodSecurity // replace with #EnableReactiveMethodSecurity for reactive app
#Configuration
public class SecurityConfig {
}
com.c4-soft.springaddons.security.issuers[0].location=https://xxxxxxxxx.okta.com/
com.c4-soft.springaddons.security.issuers[0].authorities.claims=groups
com.c4-soft.springaddons.security.permit-all=/,/welcome
# following might be too permissive, restrict if needed
com.c4-soft.springaddons.security.cors[0].path=/**
With Spring spring-boot-starter-oauth2-resource-server only, there is quite some more Java conf to write (refer to first tutorial)
Do not forget to request groups (and maybe openid and offline_access) scopes when you authenticate users from your React app or other clients like Postman.

Google Oauth2 giving "redirect_uri_mismatch" error in production when redirect uri setup correctly

I have google oauth set up in a react project. It was working fine in development, locally. Once i promoted the oauth client to "production" and modified the JS origin and redirect URIs to production values, yet it gives this error
Error 400: redirect_uri_mismatch
You can't sign in to this app because it doesn't comply with Google's
OAuth 2.0 policy.
If you're the app developer, register the redirect URI in the Google
Cloud Console. Request details:
redirect_uri=http://super-server.herokuapp.com/v1/auth/google/callback
Related developer documentation
These are the authorized redirect URIs within google cloud console:
https://super-server.herokuapp.com/v1/auth/google/callback
https://super-server.herokuapp.com/v1/auth/google/callback/
https://www.super-server.herokuapp.com/v1/auth/google/callback
https://www.super-server.herokuapp.com/v1/auth/google/callback/
As you can see, there are no authorized uri's with an HTTP schema. Theyre not even allowed in production mode. So im not sure where this is coming from, because the server is HTTPS
server:
Any advice?
the redirect uri must exactly match the one you are adding to Google developer console
If you check the error message your app is running with
http://super-server.herokuapp.com/v1/auth/google/callback
All the ones you have added are https
May i suggest fixing your app so that it runs https. I dont think that you will be able to add http as a production redirect uri endpoint.
documentation
Obtaining OAuth 2.0 access tokens
authorization-errors-redirect-uri-mismatch
Node.js
I dont know enough about react.js but with node you should be able to do something like this
const http = require('http');
const https = require('https');
In my case (MERN + passport.js), i had a configuration that looked like:
const googleOptions = {
clientID: config.google.id,
clientSecret: config.google.secret,
passReqToCallback: true,
callbackURL: '/v1/auth/google/callback',
scope: ['profile', 'email']
};
Even though the server, the client && the configuration of the oauth client within google api console were all in production with everything setup for https, for some reason, the callbackURL kept firing with google oauth as http://my-domain.com/v1/auth/google/callback
so this fix may be hacky, but it did fix my oauth issues:
//Google Strategy
const googleOptions = {
clientID: config.google.id,
clientSecret: config.google.secret,
passReqToCallback: true,
callbackURL: config.environment == 'production' ? 'https://super-server.herokuapp.com/v1/auth/google/callback' : '/v1/auth/google/callback',
scope: ['profile', 'email']
};
Looks like the redirect_uri on the client side (React side) is set to http://super-server.herokuapp.com/v1/auth/google/callback
Change the redirect_uri on the client side from (http) http://super-server.herokuapp.com/v1/auth/google/callback to (https) https://super-server.herokuapp.com/v1/auth/google/callback.

Implicit Callback not found on this server - react and node express - deploy on Azure

I've an issue with the deployment of my react app on Azure web app service.
I've followed this guide: https://developer.okta.com/blog/2018/07/10/build-a-basic-crud-app-with-node-and-react in local environment it works, but when I've tried to deploy on Azure app service the login with okta doesn't work.
So let me explain. I've uploaded node express server on Azure node app service. The react frontend i've uploaded the "npm run build" result in an other Azure app service.
I've added the Login redirect URI and trusted origins (cors) on okta admin panel.
But during the login the online version of my app replay this issue: "Not Found The requested URL /implicit/callback was not found on this server." and the URL is " https://supportexor.azurewebsites.net/implicit/callback*id_token=qwerqwerqwerqwerqwerqwer" .
In App.js
<Route path="/implicit/callback" component={ImplicitCallback} />
In index.js
const oktaConfig = {
issuer: ...,
redirect_uri: .../implicit/callback,
client_id: ...,
};
I would like to see the "SecureRoute" after the login into my app.

How to call Google Cloud Endpoints RPC API on localhost?

EDIT I posted an issue on this and it should be fixed in release 1.9.16 of Google AppEngine SDK.
https://code.google.com/p/googleappengine/issues/detail?id=11414
I am developing a service using Google Cloud Endpoints.
Both the REST and the RPC API works great when I deploy it on App Engine. However the strange thing is, when I test the service locally (localhost), the REST calls works fine, but I am having trouble with calls using RPC.
My method signature in the backend is:
#ApiMethod(name = "user.updateprofile", httpMethod = HttpMethod.POST)
public UserProfileDto updateProfile(#Named("sessionToken") String sessionToken, UserProfileDto profile) throws UnauthorizedException { return profile; }
For simplicity I am just returning the UserProfileDto directly.
I have tried to execute the following request locally:
POST http://localhost:4567/_ah/api/rpc?prettyPrint=false
Content-Type: application/json-rpc
Accept: application/json-rpc
{
"method": "mobilebackend.user.updateprofile",
"id": "gtl_1",
"jsonrpc": "2.0",
"params": {
"sessionToken": "12345",
"resource": {
"username": "foo",
"userPrivate": true
}
},
"apiVersion": "v1"
}
When I set a breakpoint in the updateProfile method, I see that the sessionToken is correctly 12345 however the username field is null and the userPrivate field is false even though I specified it as true. The instance of UserProfileDto (profile) is not null.
The problem is that it fails to inject the values into the fields of the DTO when using RPC calls localhost. When I test it on the deployed version it works fine, and when I use REST calls it works both on localhost and when deployed on App Engine.
When I change the url in the above request to target the deployed version of my application on app engine it works just fine. https://<app-name>.appspot.com/_ah/api/rpc?prettyPrint=false
I start the service on localhost using:
mvn appengine:devserver
Do I miss some configuration in order to call the Cloud Endpoints RPC methods localhost? Or is it not supported?
I should notice that I have also tried with the auto-generated iOS client library which is using RPC and it also fails with the same error as the service fails to inject the values into the fields of the DTO object.
I have tested release 1.9.17 of Google AppEngine SDK and can confirm that using objects in RPC POST requests now works fine.

Resources