Getting Request_ResourceNotFound error when retrieving GraphServiceClient.Me data - asp.net-core-mvc

I have an ASP.NET Core application with work & school account authentication as configured by Visual Studio 2015 Update 3. I'm trying to integrate Microsoft.Graph with my application. Specifically, I'm trying to obtain user information (name, department, mail, about me, etc.) from the currently logged in user.
Following the samples for previous versions of ASP.NET MVC, I managed to make the following code work.
var token = await GetAppTokenAsync(authStringMicrosoft, graphResourceId);
var authHelper = new AuthenticationHelper() { AccessToken = token };
var graphClient = new GraphServiceClient(authHelper);
var users1 = await graphClient.Users.Request().GetAsync();
var users2 = await graphClient.Users.Request().Select("mail,givenName,surname").GetAsync();
This code is placed on the OnTokenValidated callback of OpenIdConnectEvents within OpenIdConnectOptions, on my Startup class.
app.UseOpenIdConnectAuthentication(new OpenIdConnectOptions {
// ...
Events = new OpenIdConnectEvents {
OnTokenValidated = async ctx => {
// right here
}
}
});
So far, both calls to Users work great, and the code retrieves me a list of users with the specified properties. However, whenever I try to get data from the Me property, I get an error, as described below.
User me = await graphClient.Me.Request().GetAsync();
Error:
Code: Request_ResourceNotFound
Message: Resource '65c4885a-b493-4b8d-861f-79f0b8c23ec4' does not exist
or one of its queried reference-property objects are not present.
Inner error
I don't get why am I getting this error. I have checked the permissions for the application in the Azure Management Portal, both for Windows Azure Active Directory and Microsoft Graph applications. As a test, I checked everything that is to check, and still get this error.
So, my question is: why I get this error? Do I need to add a different permission, do I need to include anything else?
Thank you in advance.

From the sample code, it looks like app token is used here. /me request is not valid in context where app token (obtained by client_credential flow) is used. It is valid only in the context of access token obtained by authorization code flow (also referred to as 3-legged flow). If you can share request-id header from the error response along with timestamp, I can confirm.

Related

.Net MAUI WebAuthenticator CallbackUrl for social logins

I'm following this guide to setup authenticating with social logins using MSAL and Web Authenticator. The example call looks like this:
WebAuthenticatorResult authResult = await WebAuthenticator.Default.AuthenticateAsync(
new Uri("https://example.com/mobileauth/Microsoft"),
new Uri("myapp://"));
But what should the second URI parameter be? In the guide it says:
The URI the flow is expected to ultimately call back to, that is registered to your app.
So how do I register a URI like that to my app?? I've tried following this guide and have 'registered' my app in azure active directory but facebook/google etc won't accept urls of the form "myapp://" as valid redirect URIs... What am I missing?
Update
So the first half of the flow is working but I keep getting errors from the OAuth providers (the green highlight in the diagram isn't working).
This from Google:
And this from Facebook:
But I've added all these valid callback URLs:
I'm afraid that example is broken.
The second URI parameter represents where your app is listening to get the authentication result.
Actually, myapp:// is not a valid URI. You should try with something like myapp://callback.
Finally got to the bottom of it thanks to this old Xamarin issue: https://github.com/xamarin/Essentials/issues/1224#issuecomment-618192336
You have to set the "CallbackPath" property in the API config like so:
.AddGoogle(g => {
g.ClientId = "{Client ID}";
g.ClientSecret = "{Client Secret}";
g.CallbackPath = "/mobileauth"; //mobileauth is api controller
g.SaveTokens = true; })
And then tell the provider of that redirect e.g. adding "https://{API-URL}/mobileauth" in google console.

Silent login using Username in Azure Active Directory in Xamarin

I am developing app using Xamarin Forms. I have created a directory on azure portal. As i see references over internet , active directory authentication uses Microsofts login page to log in.
I want to create native login form and pass user name to active directory and authenticate it.
Is it possible to pass user credentials programatically and authenticate user?
How can i pass user credentials?
I have tried following but i got "(411) Length required" exception
var request = WebRequest.Create(string.Format(#"https://login.microsoftonline.com/{0}/oauth2/token?client_id=5e811f4f-4fa4-451e-a439-ca05cabc02d7&grant_type=password&username=02atul.com#gmail.com&password=userpassword&scope=openid", tenant));
request.ContentType = "application/x-www-form-urlencoded";
request.Method = "POST";
using (HttpWebResponse response = await request.GetResponseAsync() as HttpWebResponse)
{
if (response.StatusCode != HttpStatusCode.OK)
Debug.WriteLine("Error fetching data. Server returned status code: {0}", response.StatusCode);
using (StreamReader reader = new StreamReader(response.GetResponseStream()))
{
var content = reader.ReadToEnd();
if (string.IsNullOrWhiteSpace(content))
{
Debug.WriteLine("Response contained empty body...");
}
else {
Debug.WriteLine("Response Body: \r\n {0}", content);
}
}
}
My username is my email id. Is it correct user name? As i am getting bad request error now. What's missing?
Technically you could use username and password flow which is described in more detail here with ADAL.
However, you need to revisit your scenario and understand if it really accomplishes what the Azure Active Directory Platform is for.
Users use OAuth2 based authentication to get the security and safety of only having to share their passwords with trusted identity providers like MS, FB, Google, etc... In general, the safety conscious person will NOT want to type in a password into your random website, and trust that you do not abuse that information. If you want to use AAD, you should also use our login experiences, as this is really what the customer is paying for in our service in many regards.
EDIT: If ADAL no longer supports this flow, you can simply generate the http requests yourself:
POST: https://login.microsoftonline.com/xxxxx.onmicrosoft.com/oauth2/token
Content-Type: application/x-www-form-urlencoded
resource={resource}&client_id={clientId}&grant_type=password&username={userName}&password={password}&scope=openid&client_secret={clientSecret}

SignInManager::ExternalLoginSignInAsync returns IsNotAllowed for social login

I am using Microsoft.NetCore.App v1.1.0 (Nov 16, 2016) and have built a standard MVC Web App to which I've added Social Login for Microsoft and Google following advice given at Microsoft Docs.
During the first login using Google (or Microsoft) it works as expected - i.e. following authentication of my Google account my WebApp presents me with a Registration webpage requiring me to provide an email address for association with my Google account and then I'm logged into my WebApp. Unfortunately, the same happens on the second login, so obviously registration fails as the email address is already in my AspNetUsers table.
I've put a break point on _signInManager.ExternalLoginSignInAsync() in AccountController::ExternalLoginCallback(). During first login it returns Result.Succeeded false, presumably because the email isn't registered. During second login it returns Result.IsNotAllowed which isn't handled by the following series of 'if' statements so gets handled by the 'else' block - same as for Result.Succeeded false.
Does anyone know what Result.IsNotAllowed means and why it is being set? Is there a workaround?
Thanks Will
I was just having troubles with the same thing. You probably have the following line in startup.cs:
services.AddIdentity(config => config.SignIn.RequireConfirmedEmail = true)
If you have a look at Identity source code on github you will see that IsNotAllowed is returned when email has not been confirmed yet. It does not matter if this is a third party provider or a local account. To fix this, just set EmailConfirmed = true when you create and store the ApplicationUser. In the template project that is ExternalLoginConfirmation method.
var user = new ApplicationUser { UserName = model.Email, Email = model.Email, EmailConfirmed = true};
There's actually a simpler workaround, if you want to confirm the user email coming from the social login provider at some point instead for automatically marking it as confirmed. You can retrieve the user after registering it and flag the email as confirmed, without saving this to the data repository.
var user = await _userManager.FindByLoginAsync(info.LoginProvider, info.ProviderKey);
if (!user.EmailConfirmed)
{
user.EmailConfirmed = true;
// Don't save this to the DB
}
var signInResult = await _signInManager.ExternalLoginSignInAsync();

Missing Claims and Identity Info with IdentityServer v3

I have IdentityServer with Membership Reboot and IdentityManager running on a remote server, I've used the Admin UI of IdentityManager to setup a user, and add roles & claims to said user.
I'm developing a WebApi/SPA project that will use the remote server for Auth. Using fiddler I can request a token from the IdentityManagner on the remote box and use this token to against the local WebApi where Authorization is required. If the token is valid the WebApi processes like normal, if the token is bogus I get a 401. Works great.
The problem is when I want additional information about the user none of the claims or identity information is coming across. I'm not sure if the problem is at the IdentityServer side, The WebApi side, or if I'm not doing something correctly when getting my token.
I didn't realize we needed put the claims in the Scope definition. Incase anyone else stumbles upon this I changed my scope to the following
var scopes = new List<Scope>
{
new Scope
{
Enabled = true,
Name = "publicApi",
Description = "Access to our public API",
Type = ScopeType.Resource,
IncludeAllClaimsForUser = true, //I'll filter this down later
}
};
scopes.AddRange(StandardScopes.All);
return scopes;
Further details can be found here

Windows Store App Push Notifications via Azure Service Bus

I'm trying to send a push notification to my Windows Store App developed in my laptop using VS 2013 Express. It's been few days now but I cannot figure out why I get "The Token obtained from the Token Provider is wrong" error. I use Windows Azure Notification Bus for this purpose. I use VS Server Explorer to send test notifications. I can see my laptop is being registered as a device in the Device Registration tab too. I tried the Azure portal as well, but the same error. However, when I try to connect to Service Bus Explorer 2.4.3.0 providing the connection string it throws below error.
<21:47:14> Exception: The remote server returned an error: (401) Unauthorized. Manage claim is required for this operation..TrackingId:c0c4fea2-08bc-4def-964c-ec6e690b7551_G45,TimeStamp:10/12/2014 4:17:11 PM. Method b__7e: retry 2 of 10.
FYI: I'm following below article step by step.
http://azure.microsoft.com/en-us/documentation/articles/notification-hubs-windows-store-dotnet-get-started/
Please help me. Thank you.
Mahesh
Looks like token is just expired. Make sure you obtain token each time application starts. In terms of the article you refer it means you should call method InitNotificationsAsync() to do it. Here is that method:
private async void InitNotificationsAsync()
{
var channel = await PushNotificationChannelManager.CreatePushNotificationChannelForApplicationAsync();
var hub = new NotificationHub("<hub name>", "<connection string with listen access>");
var result = await hub.RegisterNativeAsync(channel.Uri);
// Displays the registration ID so you know it was successful
if (result.RegistrationId != null)
{
var dialog = new MessageDialog("Registration successful: " + result.RegistrationId);
dialog.Commands.Add(new UICommand("OK"));
await dialog.ShowAsync();
}
}

Resources