Azure App Service - Single AppRole across Services
I have an ASPNET Core Web Site called Web-App-1 and an ASP NET Core Web API called Web-Api-1.
There is functionality in Web-Api-1 that I want to secure so that it can only be called by certain users.
I also want to know in the Web-App-1 if the current user can call the secure functionality and if not I will not offer them the chance to do so.
I can satify requirement 1 by adding an AppRole to the api's App Registration in AzureAd and checking the ClaimIdentity for that app role.
if (this.ControllerContext.HttpContext.User.HasClaim(
System.Security.Claims.ClaimsIdentity.DefaultRoleClaimType,
"SecuredApiFunctionality") == false)
{
return new UnauthorizedObjectResult("User does not have SecuredApiFunctionality role");
}
However when I look in the claims for that user within the context of Web-App-1 I cannot see "SecuredApiFunctionality". I assume this is because it is an AppRole belonging to Web-Api-1 and I am in Web-App-1.
I could define a second AppRole in Web-App-1 and setup priviledges to that too but that sounds like duplication to me. Is there a way of securing the API and the Web App using only one role?
1 answer
-
answered 2022-01-30 12:58
Mr Patience
Unfortunately, I don't there's other way to achieve what you want other than defining duplicate roles in the
App
. If you look at this sample, it is how it's done there. There are also few other resources:- Github issue for this specific sample
- Stackoverflow post mentioning similar flow (see comments)
Another approach would be to call the
API
for the user's access token and have his roles there.[Edit]:
To integrate the API call intoAuthorize
attribute you can useIAuthorizationMiddlewareResultHandler
. You can see simple example in docs or more comprehensive one in this post.
do you know?
how many words do you know
See also questions close to this topic
-
How do I add new DataSource to an already Databinded CheckBoxList
i'm building a web form that show Database's item(Tables, Rows, FK,...)
I have a CheckBoxList of Tables (
chkListTable
) which will show a new CheckBoxList of Rows (chkListRow
) everytime I SelectedIndexChanged fromchkListTable
. The problem is i can show the items fromchkListTable
with 1 selected item. But i don't know how to showchkListRow
if multiple item fromchkListTable
are selected.Here are my codes:
aspx
:<div> <asp:Label ID="Label2" runat="server" Text="Table: "></asp:Label> <asp:CheckBoxList ID="chkListTable" runat="server" DataTextField="name" DataValueFeild="name" AutoPostBack="true" OnSelectedIndexChanged="chkListTable_SelectedIndexChanged"> </asp:CheckBoxList> </div> <div> <asp:CheckBoxList ID="chkListRow" runat="server" DataTextField="COLUMN_NAME" DataValueField="COLUMN_NAME" RepeatDirection="Horizontal"> </asp:CheckBoxList> </div>
aspx.cs
:protected void chkListTable_SelectedIndexChanged(object sender, EventArgs e) { tableName.Clear(); foreach (ListItem item in chkListTable.Items) { if(item.Selected) { tableName.Add(item.Text.Trim()); } } for(int i = 0; i < tableName.Count; i++) { String query = "USE " + dbname + " SELECT * FROM information_schema.columns" + " WHERE table_name = '" + tableName[i] + "'" + " AND COLUMN_NAME != 'rowguid'"; chkListRow.DataSource = Program.ExecSqlDataReader(query); chkListRow.DataBind(); Program.conn.Close(); } }
Program.cs
:public static bool Connect() { if (Program.conn != null && Program.conn.State == ConnectionState.Open) Program.conn.Close(); try { Program.conn.ConnectionString = Program.constr; Program.conn.Open(); return true; } catch (Exception e) { return false; } } public static SqlDataReader ExecSqlDataReader(String query) { SqlDataReader myreader; SqlCommand sqlcmd = new SqlCommand(query, Program.conn); sqlcmd.CommandType = CommandType.Text; if (Program.conn.State == ConnectionState.Closed) Program.conn.Open(); try { myreader = sqlcmd.ExecuteReader(); return myreader; myreader.Close(); } catch (SqlException ex) { Program.conn.Close(); return null; } }
I want my display to be like this:
[x]Table1 [x]Table2 [ ]Table3 [ ]Row1(Table1) [ ]Row2(Table1) [ ]Row3(Table1) [ ]Row1(Table2) [ ]Row2(Table2)
-
Writing multithreaded code to generate incremental index
I want to write a code in following scenario : we want to design an invoice generator.this invoice generator also generates an incremental invoice no .Also note that for some reasons we dont use something like sql Auto Increment here and we want to use C# (I wrote the increment logic). since several users can send requests at a time it means that we dont have to give the same invoice no to them (I used lock for it and I wrote it).
Now i have written increment logic. and i take care of multiple users requests with lock . and I wrote CRUD for mongodb database.
My problem is that my increent logic is naive. each time i find maximum and i increment by one which is not scalable. and another problem is that when we delete a record we don't want the invoice no to be repeated and since we find max if the deleted record had the max value then the invoice no would be duplicate and this is something we don't want to have.
I really don't know how to handle the problem. specially in case of deletion should i store max values in a file or should i change increment logic completely?
i appreciate any help
-
Scraping .aspx page with Python yields 404
I'm a web-scraping beginner and am trying to scrape this webpage: https://profiles.doe.mass.edu/statereport/ap.aspx
I'd like to be able to put in some settings at the top (like District, 2020-2021, Computer Science A, Female) and then download the resulting data for those settings.
Here's the code I'm currently using:
import requests from bs4 import BeautifulSoup url = 'https://profiles.doe.mass.edu/statereport/ap.aspx' with requests.Session() as s: s.headers['User-Agent'] = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:100.0) Gecko/20100101 Firefox/100.0" r = s.get('https://profiles.doe.mass.edu/statereport/ap.aspx') soup = BeautifulSoup(r.text,"lxml") data = {i['name']:i.get('value','') for i in soup.select('input[name]')} data["ctl00$ContentPlaceHolder1$ddReportType"]="DISTRICT", data["ctl00$ContentPlaceHolder1$ddYear"]="2021", data["ctl00$ContentPlaceHolder1$ddSubject"]="COMSCA", data["ctl00$ContentPlaceHolder1$ddStudentGroup"]="F", p = s.post(url,data=data)
When I print out
p.text
, I get a page with title'\t404 - Page Not Found\r\n'
and message<h2>We are unable to locate information at: <br /><br ' '/>http://profiles.doe.mass.edu:80/statereport/ap.aspxp?ASP.NET_SessionId=bxfgao54wru50zl5tkmfml00</h2>\r\n'
Here's what
data
looks like before I modify it:{'__EVENTVALIDATION': '/wEdAFXz4796FFICjJ1Xc5ZOd9SwSHUlrrW+2y3gXxnnQf/b23Vhtt4oQyaVxTPpLLu5SKjKYgCipfSrKpW6jkHllWSEpW6/zTHqyc3IGH3Y0p/oA6xdsl0Dt4O8D2I0RxEvXEWFWVOnvCipZArmSoAj/6Nog6zUh+Jhjqd1LNep6GtJczTu236xw2xaJFSzyG+xo1ygDunu7BCYVmh+LuKcW56TG5L0jGOqySgRaEMolHMgR0Wo68k/uWImXPWE+YrUtgDXkgqzsktuw0QHVZv7mSDJ31NaBb64Fs9ARJ5Argo+FxJW/LIaGGeAYoDphL88oao07IP77wrmH6t1R4d88C8ImDHG9DY3sCDemvzhV+wJcnU4a5qVvRziPyzqDWnj3tqRclGoSw0VvVK9w+C3/577Gx5gqF21UsZuYzfP4emcqvJ7ckTiBk7CpZkjUjM6Z9XchlxNjWi1LkzyZ8QMP0MaNCP4CVYJfndopwFzJC7kI3W106YIA/xglzXrSdmq6/MDUCczeqIsmRQGyTOkQFH724RllsbZyHoPHYvoSAJilrMQf6BUERVN4ojysx3fz5qZhZE7DWaJAC882mXz4mEtcevFrLwuVPD7iB2v2mlWoK0S5Chw4WavlmHC+9BRhT36jtBzSPRROlXuc6P9YehFJOmpQXqlVil7C9OylT4Kz5tYzrX9JVWEpeWULgo9Evm+ipJZOKY2YnC41xTK/MbZFxsIxqwHA3IuS10Q5laFojoB+e+FDCqazV9MvcHllsPv2TK3N1oNHA8ODKnEABoLdRgumrTLDF8Lh+k+Y4EROoHhBaO3aMppAI52v3ajRcCFET22jbEm/5+P2TG2dhPhYgtZ8M/e/AoXht29ixVQ1ReO/6bhLIM+i48RTmcl76n1mNjfimB8r3irXQGYIEqCkXlUHZ/SNlRYyx3obJ6E/eljlPveWNidFHOaj+FznOh264qDkMm7fF78WBO2v0x+or1WGijWDdQtRy9WRKXchYxUchmBlYm15YbBfMrIB7+77NJV+M6uIVVnCyiDRGj+oPXcTYxqSUCLrOMQyzYKJeu8/hWD0gOdKeoYUdUUJq4idIk+bLYy76sI/N2aK+aXZo/JPQ+23gTHzIlyi4Io7O6kXaULPs8rfo8hpkH1qXyKb/rP2VJBNWgyp8jOMx9px+m4/e2Iecd86E4eN4Rk6OIiwqGp+dMdgntXu5ruRHb1awPlVmDw92dL1P0b0XxJW7EGfMzyssMDhs1VT6K6iMUTHbuXkNGaEG1dP1h4ktnCwGqDLVutU6UuzT6i4nfqnvFjGK9+7Ze8qWIl8SYyhmvzmgpLjdMuF9CYMQ2Aa79HXLKFACsSSm0dyiU1/ZGyII2Fvga9o+nVV1jZam3LkcAPaXEKwEyJXfN/DA7P4nFAaQ+QP+2bSgrcw+/dw+86OhPyG88qyJwqZODEXE1WB5zSOUywGb1/Xed7wq9WoRs6v8rAK5c/2iH7YLiJ4mUVDo+7WCKrzO5+Hsyah3frMKbheY1acRmSVUzRgCnTx7jvcLGR9Jbt6TredqZaWZBrDFcntdg7EHd7imK5PqjUld3iCVjdyO+yLKUkMKiFD85G3vEferg/Q/TtfVBqeTU0ohP9d+CsKOmV/dxVYWEtBcfa9KiN6j4N8pP7+3iUOhajojZ8jV98kxT0zPZlzkpqI4SwR6Ys8d2RjIi5K+oQul4pL5u+zZvX0lsLP9Jl7FeVTfBvST67T6ohz8dl9gBfmmbwnT23SyuFSUGd6ZGaKE+9kKYmuImW7w3ePs7C70yDWHpIpxP/IJ4GHb36LWto2g3Ld3goCQ4fXPu7C4iTiN6b5WUSlJJsWGF4eQkJue8=', '__VIEWSTATE': '/wEPDwUKLTM0NzY4OTQ4NmRkDwwPzTpuna+yxVhQxpRF4n2+zYKQtotwRPqzuCkRvyU=', '__VIEWSTATEGENERATOR': '2B6F8D71', 'ctl00$ContentPlaceHolder1$btnViewReport': 'View Report', 'ctl00$ContentPlaceHolder1$hfExport': 'ViewReport', 'leftNavId': '11241', 'quickSearchValue': '', 'runQuickSearch': 'Y', 'searchType': 'QUICK', 'searchtext': ''}
Following suggestions from similar questions, I've tried playing around with the parameters, editing
data
in various ways (to emulate the POST request that I see in my browser when I navigate the site myself), and specifying anASP.NET_SessionId
, but to no avail.How can I access the information from this website?
-
Fluent Validation with conditions in asp.net core
I am working in asp. net core 6.0 web API project (clean architecture (CQRS)).
I am using fluent validation for validate command and queries.
public class CreateSiteDestinationSectionsCommand : IRequest<x> { public int DestinationSectionId { get; set; } public int DestinationSectionTitleId { get; set; } public int SiteCodeId { get; set; } public string Description { get; set; } public List<DestinationImageDto> Images { get; set; } public List<string> Links { get; set; } }
This is i did inside CreateSiteDestinationSectionsCommandHandler.
var DestinationSectionTitleId = request.DestinationSectionTitleId; if (DestinationSectionTitleId != 10) { if (DestinationSectionTitleId == 1 || DestinationSectionTitleId == 2 || DestinationSectionTitleId == 5 || DestinationSectionTitleId == 7 || DestinationSectionTitleId == 8 || DestinationSectionTitleId == 9 || DestinationSectionTitleId == 11) { var sectionimageCount = request.Images.Count; if (sectionimageCount != 1) { throw new ApiValidationException("Section has not more than one image"); } else (DestinationSectionTitleId == 10 && request.Images != null) { var sectionimageCount = request.Images.Count; if (sectionimageCount != 0) { throw new ApiValidationException("Section doesnot have any image"); } } } }
But instead of handling validation inside commandHandler, I have to handle validation in CreateSiteDestinationSectionsCommandValidator.
I tried this,
RuleFor(x => x.Images) .Must(x => x != null) .When(x => x.DestinationSectionId != 10) .WithMessage("Site Section image required"); RuleFor(x => x.DestinationSectionId).NotEmpty(); RuleFor(x => x.Images) .Must(x => x.Count != 1) .When(x => x.DestinationSectionId == 1 && x.DestinationSectionId == 1 && x.DestinationSectionId == 2 && x.DestinationSectionId == 5 && x.DestinationSectionId == 7 && x.DestinationSectionId == 8 && x.DestinationSectionId == 9 && x.DestinationSectionId == 11 ) .WithMessage("Site Section has not more than one image"); }
When I check throug postman request, Even I send with DestinationSectionId = 10 (and not sending any images), I got validation error as
"errors": { "Images": [ "Site Section image required" ] }
And Even I send more than 1 images for DestinationSectionId = 1, I did not get validation error. BUT I shoud get validation error as
Site Section has not more than one image
Why this validations not work correctly? What I missed?
-
Using RestSharp to request a file fails with memory issue
I have to API's talking to each other on Kubernetes. The first API asks the second API for a small file using RestSharp (in ASP.NET). The file is 8Kb so basically not large at all.
Yet i get the following message on the API that wants to receive the file:
Exception of type 'System.OutOfMemoryException' was thrown. at RestSharp.RestClient.ThrowIfError(RestResponse response) at RestSharp.RestClientExtensions.GetAsync(RestClient client, RestRequest request, CancellationToken cancellationToken) at Aftermarket.Server.AdministrationService.Server.Services.Services.RunSessionService.DownloadRunSession(String foldername) in /src/Aftermarket.Server.DbApi/Server/Services/Services/RunSessionService.cs:line 59
The code U use to call the other API and ask for the file looks as follows:
public async Task<byte[]> DownloadRunSession(string foldername) { try { var request = new RestRequest($"{config["WebApiServer:WebApiServerUrl"]}/blob/{foldername}"); var response = await client.GetAsync(request); if (!response.IsSuccessful) { Console.WriteLine("File download failed"); Console.WriteLine(response.StatusCode); return null; } return response.RawBytes; }catch(Exception e) { Console.WriteLine(e.Message); Console.WriteLine(e.StackTrace); return null; } }
The API that responds by sending the file has the following controller method:
public IActionResult GetBlob([FromQuery] string folderName, [FromServices] GetBlobsService _getBlobsService) { _logger.Info(folderName); Guid guid = Guid.NewGuid(); if (_env.EnvironmentName == "dev" || _env.EnvironmentName == "prod") { byte[] blob = _getBlobsService.GetBlob(folderName, guid, _logger); if (blob == null) return this.NotFound(); else { return File(blob, "application/force-download", guid + ".zip"); } } else { return Content("This function is only available in Dev/Uat Environment"); } }
Any one have any idea how a 8Kb file is causing this issue?
-
How is Windows Authentication Wired Up?
I'm in the process of creating an ASPNET Core 6 MVC app in VS 2022 which will eventually be deployed in a Docker container. Windows Authentication will be used as it's an internal app. When creating this project from scratch with File -> New Project -> ASP.NET Core 6 Web App (Model-View-Controller) and with Windows Authentication enabled, everything works as expected.
This is where it gets weird. Since this will be a Docker container on Linux, I commented out the IIS settings in launchSettings.json.
{ //"iisSettings": { // "windowsAuthentication": true, // "anonymousAuthentication": false, // "iisExpress": { // "applicationUrl": "http://localhost:60583", // "sslPort": 44391 // } //}, "profiles": { "ASPNETCORE6": { "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, "applicationUrl": "https://localhost:7276;http://localhost:5276", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } }, "IIS Express": { "commandName": "IISExpress", "launchBrowser": true, "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } } } }
To recreate this issue, comment out the following from the generated Program.cs file:
//using Microsoft.AspNetCore.Authentication.Negotiate; //builder.Services.AddAuthentication(NegotiateDefaults.AuthenticationScheme) // .AddNegotiate(); //builder.Services.AddAuthorization(options => //{ // options.FallbackPolicy = options.DefaultPolicy; //}); //app.UseAuthentication(); //app.UseAuthorization();
Now, when I run a debugging session using IIS Express, the browser windows renders with my correct domain name being displayed. How is this even possible? Is something being cached? Also, the browser is going to http://localhost:44391/ when debugging with IIS Express even though this is commented out in launchSettings.json.
Note: Windows authentication is not working when I debug with Kestrel, which is what I would expect.
-
How to authorize azure container registry requests from .NET CORE C#
I have a web application which creates ContainerInstances, I have specific container registry images I want to use. As a result, I use this code to get my azure container registry
IAzure azure = Azure.Authenticate($"{applicationDirectory}/Resources/my.azureauth").WithDefaultSubscription(); IRegistry azureRegistry = azure.ContainerRegistries.GetByResourceGroup("testResourceGroup", "testContainerRegistryName");
I get this error when the second line of code is hit
The client 'bc8fd78c-2b1b-4596-827e-6a3c918b7c17' with object id 'bc8fd78c-2b1b-4596-827e-6a3c918b7c17' does not have authorization to perform action 'Microsoft.ContainerRegistry/registries/read' over scope '/subscriptions/506b787d-83ef-426a-b7b8-7bfcdd475855/resourceGroups/testapp-live/providers/Microsoft.ContainerRegistry/registries/testapp' or the scope is invalid. If access was recently granted, please refresh your credentials.
I literally have no idea what to do about this. I have seen so many articles talking about Azure AD and giving user roles and stuff. Can someone please walk me step by step how to fix this? I REALLY appreciate the help. Thanks.
I cannot find any client under that object ID so perfectly fine starting from scratch again with a better understanding of what I am doing.
-
Token is generating with all the available scopes in AzureAD
I have below setup on Azure,
- Host APP
- Added 3 Scopes under "Expose an API" tab i.e. abc, def, ghi
- Client APP
- Added all 3 Scopes under "API Permissions" tab
Now if I request the token from Postman for Client APP with specific scope(s) and I decode the token over JWT.IO then I all 3 scopes available in "scp" claim.
POSTMAN Setup for OAuth 2.0,
My expectation here is to implement scope based authorization where If I request the token for abc scope then only ABC should present in token.
- Host APP
-
facing issue while using synapsesql (####.dfs.windows.core.net not found)
I was working on connecting dedicated sql pool(formerly sql DWH) to synapse spark notebooks. I was using spark.read.synapsesql(). I'm able to write data as table but not able to read data from the table.
val df:DataFrame = spark.read.option(Constants.SERVER, "XXXXX.database.windows.net") .option(Constants.USER, "XXXXX") .option(Constants.PASSWORD, "XXXXX") .option(Constants.TEMP_FOLDER,"abfss://xxxxx@xxxx.dfs.core.windows.net/Tempfolder/") .synapsesql("dedicated-poc.dbo.customer"
com.microsoft.spark.sqlanalytics.SQLAnalyticsConnectorException: com.microsoft.sqlserver.jdbc.SQLServerException: External file access failed due to internal error: 'Error occurred while accessing HDFS: Java exception raised on call to HdfsBridge_Connect.
Java exception message: Configuration property XXXXXXXX.dfs.core.windows.net not found.' at com.microsoft.spark.sqlanalytics.ItemsScanBuilder$PlanInputPartitionsUtilities$.extractDataAndGetLocation(ItemsScanBuilder.scala:183)
Permission: we have owner, storage data blob contributor access for synapse and specific user
-
Azure B2C broken when explicitly-declared value for android:exported is used
My Xamarin.Forms application uses Azure AD B2C for authentication. Currently, I have to use Android 12 instead of Android 10. According to the documentation, it required a certain change:
Warning: If an activity, service, or broadcast receiver uses intent filters and doesn't have an explicitly-declared value for android:exported, your app can't be installed on a device that runs Android 12 or higher.
(https://developer.android.com/about/versions/12/behavior-changes-12#security)
This is my code from MsalActivity.cs:
namespace UserDetailsClient.Droid { [Activity(Exported = false)] [IntentFilter(new[] { Intent.ActionView }, Categories = new[] { Intent.CategoryBrowsable, Intent.CategoryDefault }, DataHost = "auth", DataScheme = "msal5c32fe58-4a77-49ea-8b5d-010c4a684e4f")] public class MsalActivity : BrowserTabActivity { } }
After I added (Exported = false), I was able to deploy and run the app. But now I am not able to log in. The login screen does show up. And the user can enter the credentials, but after submitting, we get stuck on this screen:
Nothing new appears in the output window. How can this be diagnosed and fixed?
-
Web App MSAL error, 200 error on redirect
Errors:
Access to fetch at 'https://login.microsoftonline.com/{bunchofinfo}' (redirected from 'http://localhost:5000/login') from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource. If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.
GET https://login.microsoftonline.com/{bunchofinfo} net::ERR_FAILED 200
Code:
@app.route("/") def index(): if not session.get("user"): return redirect(url_for("login")) return redirect('http://localhost:3000/') @app.route("/login") def login(): session["flow"] = _build_auth_code_flow(scopes=SCOPE_MSAL) auth_url = session["flow"]["auth_uri"] print(auth_url) return redirect(auth_url)
Things Ive tried: First tried to set {'mode': 'no-cors'} and redirect. But it gives me the HTML for the redirect and doesn't redirect me.
Then tried sending my frontend the auth_url with no redirect. Then window.location.assign(auth_url) Problem = Once logged on properly, it stays on localhost:5000/login with the auth_url on the page. Tried to switch code with this but it doesn't move on after login and runs the if not statement.
def login(): if not session.get("user"): session["flow"] = _build_auth_code_flow(scopes=SCOPE_MSAL) auth_url = session["flow"]["auth_uri"] print(auth_url) return auth_url return redirect('http://localhost:3000')
Don't know how to proceed. Rest of code from MSAL
@app.route("/getAToken") def authorized(): try: cache = _load_cache() result = _build_msal_app(cache=cache).acquire_token_by_auth_code_flow( session.get("flow", {}), request.args) if "error" in result: print(result) # add error page # return render_template("auth_error.html", result=result) session["user"] = result.get("id_token_claims") _save_cache(cache) except ValueError: # Usually caused by CSRF pass # Simply ignore them return redirect(url_for("index")) def _load_cache(): cache = msal.SerializableTokenCache() if session.get("token_cache"): cache.deserialize(session["token_cache"]) return cache def _save_cache(cache): if cache.has_state_changed: session["token_cache"] = cache.serialize() def _build_msal_app(cache=None, authority=None): return msal.ConfidentialClientApplication( microsoft_client_id, authority=authority or AUTHORITY, client_credential=client_secret, token_cache=cache) def _build_auth_code_flow(authority=None, scopes=None): return _build_msal_app(authority=authority).initiate_auth_code_flow( scopes or [], redirect_uri=url_for("authorized", _external=True)) def _get_token_from_cache(scope=None): cache = _load_cache() # This web app maintains one cache per session cca = _build_msal_app(cache=cache) accounts = cca.get_accounts() if accounts: # So all account(s) belong to the current signed-in user result = cca.acquire_token_silent(scope, account=accounts[0]) _save_cache(cache) return result
-
Can you add higher authority to client on backend after SPA MSAL app login?
I would like to create an spa app with MSAL using react or nextjs. Is there a way to add a client secret or give higher authority on my backend after the user logged on from the spa version of MSAL?
What I am trying to do: I want the user to log in and get their email from https://graph.microsoft.com/v1.0/me in the spa.(Which I am currently getting).
Afterwards I want to send that email to my backend to call dynamics CRM. https://{TENANT}api/data/v9.0/accounts
Problem: The spa wont have a client secret attached, so the access_token is public, not allowing me to make the CRM call. I tried to make it a web app instead, but the redirecting from that MSAL messes up on my frontend (The sessions cant be deleted properly). Can I do something with the MSAL SPA or do I need to find a work around on the webApp version?
-
Validating tenant in multitenant React apps using MSAL
We're working on moving some apps from Razor Pages to React, and we'd like to use Microsoft Identity Platform for authentication via MSAL.
Some of these apps are multi-tenant, and we want to be able to validate that a given tenant is set up and authorized when a user logs in. Today, we do that in .NET via the
OnTokenValidated
event by pulling the email domain or tenant ID from the token claims and comparing it to our app's list of authorized tenants in our databases.In MSAL, I'm not entirely clear how to accomplish that. The MS docs say, "If you allow multi-tenant authentication, and you do not wish to allow all Microsoft account users to use your application, you must provide your own method of filtering the token issuers to only those tenants who are allowed to login" (in https://github.com/AzureAD/microsoft-authentication-library-for-js/blob/dev/lib/msal-angular/docs/multi-tenant.md#multi-tenant).
Where in the React login or token acquisition process can I inspect the claims in order to perform this filtering? How are others handling these kinds of checks with MSAL on a SPA front-end framework like React?
-
Generating token for client not working - Microsoft.Identity.Client
I am trying to generate a JWT token for client. I have below code
var clinetid = "xxxxxxxx-b98c-4bd4-a3d7-xxxxxxxxxxxx"; var clientSecret = "UxpoxboRY0t-xxxxx~jF5~DFxxxx_xxxxx"; var authority = "https://login.microsoftonline.com/xxx.onmicrosoft.com"; IConfidentialClientApplication app = ConfidentialClientApplicationBuilder.Create(clinetid) .WithClientSecret(clientSecret) .WithAuthority(new Uri(authority)) .Build(); string[] scopes = new string[] { "api://xxxxxxxx-b98c-4bd4-a3d7-xxxxxxxxxxxx/.default" }; AuthenticationResult result = await app.AcquireTokenForClient(scopes).ExecuteAsync();
I am running this code from Windows from application -> class library project (.net framework 4.6.1) but this never get executed. I am using Microsoft.Identity.Client 4.43.1 Is there anything I am missing here if anyone can direct me
-
Why should I enabled OAuth from APIM when it is already secure using Microsoft Identity platform
I have created a Web API using .net core 5. I have secured the app using the Microsoft Identity platform. Clients app are able to get to the resource based on their scope/role. So I know that my api is secure.
Now, I need to add the API to Azure API Management tool. So my question is should I enable OAuth from the Azure API Management to secure my web api even though my app is already secured?. What would be the reason that I enable OAuth from API management?