How to handle Azure B2C errors in a centralized manner? Instead of sending it back to the web app - error-handling

In many cases, Azure B2C send error code and message back to the web app. For example, when you use ValidTokenIssuerPrefixes to define an acceptable Azure AD tenant, and when the user is not from one of the tenants, the following error will be sent back to the web app:
https://[my_web_redirect_uri]/#error=invalid_request&error_description=AADB2C90238%3a+The+provided+token+does+not+contain+a+valid+issuer.+Please+provide+another+token+and+try+again.%0d%0aCorrelation+ID%3a+98d02f12-8df7-49eb-9782-6eb2eaea4e30%0d%0aTimestamp%3a+2022-11-02+16%3a59%3a22Z%0d%0a
When this redirect reaches the web app, it’s up to the web app to display/translate this error. This mechanism is fine when you have a handful of web apps. In my case, I have many web apps that use a single custom sign-in policy. I want to have a centralized page or mechanism to handle the error. I search the internet but haven’t found any answer. Does anyone have a similar concern and solution?

Related

Using Microsoft.Identity.Web to authenticate users for WebApp+API, and how to manage lifecycle

I'm trying to create a webapp that uses multi-tenant Azure AD for authentication & authorization. I'm trying to follow the docs, using Microsoft.Identity.Web, and the pieces aren't clicking for me.
I've been able to successfully create a web app where users are able to login, get redirected back to my site, and get an id_token saved to their browser cookies so the web app is able to tell who they are. However, my web app also contains APIs itself, and it isn't clear to me how we're supposed to obtain an access_token, as well as manage the lifecycle by way of refresh_tokens, for calling APIs on the web app itself. In fact, refresh doesn't seem to be covered at all in the docs for Microsoft.Identity.Web.
Instead of the dedicated SDK, I've also tried using AddCookie()+AddOpenIdConnect() (the more generic solution). Using these middleware options I've successfully been able to obtain an id_token, access_token, and refresh_token. (Which seems to connect all the pieces of access, and refresh/lifecycle.) However, all of those tokens take up a fair amount of cookie space, and cause 431 Request Header Fields Too Large errors from Kestrel without customization.
It's clear that the intention is for access/refresh tokens to be stored server-side on some sort of in-memory or distributed cache. However, the documentation doesn't seem to outline how to deal with "web apps" that ALSO contain API controllers, and furthermore doesn't seem to outline how to deal with token refreshes in general.
Does anyone have any better in-code examples of how to configure a WebApp that authenticates users with Azure AD, and also properly handles refreshing the id/access tokens using the refresh_token?
Refresh tokens are automatically handled by MSAL.NET, which is used by Microsoft.Identity.Web.
We suggest you have a look at the following sample: https://github.com/Azure-Samples/active-directory-aspnetcore-webapp-openidconnect-v2/tree/master/4-WebApp-your-API/4-3-AnyOrg but you would have the same clientID (and app) for your web app and web API.
Please also look at https://github.com/AzureAD/microsoft-identity-web/wiki/Mixing-web-app-and-web-api-in-the-same-ASP.NET-core-app

Azure AD or IdentityServer with Web API, understanding the concepts

Be warned possibly noob question ahead.
I'm a little unsure where exactly Azure AD or IdentityServer is supposed to fit in in the overall communication flow.
Here is a scenario that I often face.
Some "dumb" client (e.g. a Windows App that can't use external assemblies or some JavaScript in a web app) has to contact my Web API which will then contact other APIs or other resources.
If I want to try and implement either Azure AD or IdentityServer as a means of authentication and authorization in the Web API, I don't see that this can be done in any other way, than it has to be the Web API that communicates with Azure AD or IdentityServer as the client doesn't have the ability to do so due to the lack of required assemblies.
If this assumption is not correct, then how would I do this?
If it is correct however, then what means of security is there between the client and the Web API other than communicating over HTTPS when the client has to send it's credentials to the Web API, so the Web API can authenticate and authorize the user against either Azure AD or IdentityServer?
If I understand your requirements correctly, then you are able to change the client Windows app, but unable to add external assemblies to it? So you would not be able to add the ADAL NuGet package to it.
You can still use Azure AD authentication - it is possible, but not trivial, to implement the client code yourself.
Or you can, as you already mentioned, pass the user's credentials to the Web API somehow, and then use that to have the Web API do authentication towards Azure AD on behalf of the user. There is a sample app which shows how to use username/password credentials.
This however, goes against the whole OAuth/OpenIdConnect mindset, where your app should never know the user's credentials.
Here:
https://github.com/MicrosoftDocs/azure-docs/blob/master/articles/active-directory/develop/active-directory-v2-protocols-oidc.md
Be careful with trying to use the most recent version of the Azure AD endpoint (just don't use version 2.0, they shot themselves in the foot by excluding all Azure AD webapp registrations & by "securing" web APIs by making them only available to apps with the same appid - as far as I'm concerned, it's unusable until they fix those two issues) - see the "[!NOTE]" near the top of that linked page for the v2.0 limitations.

Authenticating Xamarin Forms app with Azure Active Directory for accessing a protected Azure AAD Web API app

Not sure how to go about doing this; I'm not looking for B2C, I don't want my users to sign in. I just want my Xamarin app to be able to access an Azure AAD protected API. In other words, I want to authenticate the app itself with the Azure Active Directory, to access an Azure AAD protected API. From what I've found on the internets, service principal to service principal auth is discouraged when using mobile apps and I've not really found a way to do it service to service anyhow.
Any suggestions on how to properly do this? Links with tutorials would be great.
Thanks!
Azure does provide the ability to generate a client ID which you could have sent from your application and checked. Microsoft talk about this in this article. You will want to be careful with how you store this ID in your app as if someone were to steal this they would be able to access your API. Along with that you'd also want to make sure that your connection between your app and server is secured with a pinned SSL certificate so it cannot be man-in-the-middle'd.
Another interesting approach is software attestation where some service checks various aspects of your app to ensure that it is your app. Full disclosure, I work for a company which does this. See Approov. We take a fingerprint of your app and our SAAS checks that this matches at run time. We then issue a token which your app can use to prove that it is the real app.

Azure API App anonymous users and authentication

After looking through multiple tutorials and posts, I have not found an answer or guide as to how to handle the following issue:
There is an Azure API App communicating with an Azure DocumentDB
There will be an Azure Web App (and some day mobile apps) communicating with the API App.
I would like for anonymous users to have access to read only information through the Web App (and only through the Web App). The
API App will serve up documents as requested. Anonymous users
connecting directly to the API App should not be allowed to retrieve
any information.
For contributors, they will be able to add documents using the Web App
when they are logged in. The documents will go through the API App
to be written to the DocumentDB
What are the suggested ways for handling anonymous users and authenticated users so both can use the Web App and the underlying API App successfully while blocking any use of the API App if it does not come from the Web App (or future mobile apps)? I only want anonymous users to be able to retrieve information when using the Web App.
The API App is developed in C# .NET 4.5, and the Web App will be the same. I'm not planning on writing my own authentication since the Azure Gateway takes care of this, but it only has the options of Public (Anonymous), Public (Authenticated), and Internal. Public (Anonymous) lets everyone in, while Public (Authenticated) blocks the anonymous users that I would like to have read only access. I'm very new to dealing with Authentication so I'm not even sure if this is possible without having to write my own authentication engine.
For clarification, this question is purely for Authentication between the Web App and the API App.
Thanks,

Securing ASP.Net Web API with API Key

I'm developing an ASP.Net MVC 4 Web API application where this application will be the source data for different Mobile/Web client apps. I need to authenticate a user so I can return the correct set of content for the user. I'm thinking about using an API Key that is sent to every request of my Web API application. The API Key identifies the user. I found this post that outlines a potential solution: From API Key to User with ASP.NET Web API
I need to support forms authentication as well as oAuth 2.0 for Facebook, Twitter, etc. All of these approaches yield a token I can use to send back and forth from the different clients to my Web API so I can identify the user. I understand Facebook access tokens expire. I'm a little confused on what's the best way to deal with Facebook interactions. Which of the following paths is the best way to go:
Rely on the different client apps to authenticate against Facebook (and other oAuth providers) to establish a Facebook access token that's then forwarded to my Web API application? This means all of the clients are responsible for making sure the Facebook access token is not expired. The Web API app assumes the access token is always valid. This seems dangerous to me. The different apps would authenticate the user then send user information to WebAPI app to register the user in order for the user to consume the data from my Web API app. This seems like a lot of duplication.
Make my Web API application solely responsible for interacting with Facebook (and other oAuth providers) on behalf of all the different client apps using my Web API. So this approach seems to suggest I need to build some sort of authenticating UI for my Web API app. I know ASP.Net MVC Web API can have views and front end stuff, but it always seems to me that you are mixing things together. It seems Web API apps should be singularly focused on returning data. Users from all of the different client apps will register with my Web Api app by either filling out a registration form, or using Facebook, Twitter, etc. Is it OK to mix UI views in with a pure REST Web API application? Then you have to start worrying about everything that goes with UIs on different devices, etc.
Is there another way I'm not seeing?
I really appreciate any guidance and links to examples you might have. Thanks for your time.
I would suggest you below approach:
1. Create an authentication API which will authenticate the user. If user is authenticated successfully, create a session (self implemented, may be a record in your db) for that user.
2. Next time user call your other APIs which returns content for that user. In this case it would be must for that user to provider the session id (which you have created in first step) to get the content. If sessionId provided by user does not exist at your end, it means the user is not authenticated. In this case you can return authentication error message to the user telling that he needs to get authenticated first. It is very flexible, scaleable solution in a way that you can store many information regarding that user session. Also once authenticated, user does not need to get authenticated every time he calls your other APIs to get content. It would save you as well from authenticating the user every time.