GithubHelp home page GithubHelp logo

microsoftgraph / aspnetcore-connect-sample Goto Github PK

View Code? Open in Web Editor NEW
122.0 17.0 96.0 1.53 MB

[ARCHIVED] This ASP.NET Core MVC sample shows how to connect to Microsoft Graph using delegated permissions and the Azure AD v2.0 (MSAL) endpoint.

License: MIT License

C# 66.56% CSS 1.52% JavaScript 0.07% HTML 31.85%
devxsample

aspnetcore-connect-sample's People

Contributors

bgavrilms avatar jasonjoh avatar jthake avatar juanpescador avatar madansr7 avatar mark-szabo avatar microsoft-github-policy-service[bot] avatar mrcl1450 avatar nokafor avatar pekspro avatar supernova-eng avatar tbolon avatar tstojecki avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aspnetcore-connect-sample's Issues

Azure AD B2C

Is there an equivalent solution utilizing Azure AD B2C?

Is it even compatible with Microsoft Graph API?

I'm unable to get tokens generated via my B2C portal to authenticate against the Graph API.

How to add admin consent?

I have tried so many things to try and modify this to acquire a token on behalf of the client only, and use Application level permissions to read mail. Every time I get Unauthorized access errors.

How do I implement admin consent into the flow for this?

AADSTS90130: Application '{application id}' (aad name) is not supported over the /common or /consumers endpoints. Please use the /organizations or tenant-specific endpoint.

I have been using the .Net Core 2.0 sample which uses the Azure AD endpoint, so that we registered using our company Azure Portal.

I have already set the client id, base URL, reply url, tenant id in my appsettings. Is there any work around or fix for this issue?

https://github.com/microsoftgraph/aspnetcore-connect-sample/tree/netcore1.1

Restart IIS in production returns error if user is logged in

I build an application and use the microsoft graph for login and logout. When a user is logged in via microsoft graph and in the same time i restart the iis server.If the user refersh the page the token is invalid and returns an error page.

What steps can i do, so when i restart the iis , the logged in user refreshes the token automatically via the microsoft graph api

After signin in to AAD - Exception: Correlation failed.

Hi,
I've followed the sample, when I run the IIS on localhost and click Sign In then go through the authentication process I end up with:

An unhandled exception occurred while processing the request.

Exception: Correlation failed.
Unknown location

Exception: An error was encountered while handling the remote login.
Microsoft.AspNetCore.Authentication.RemoteAuthenticationHandler.HandleRequestAsync()

Migrate to Azure AD v2

This sample still use the Azure AD v1 endpoint. Do you plan to migrate to the new v2.0 endpoint ?

Migrate to MSAL.NET 2.x

Given the new update to MSAL Net 2 (https://github.com/AzureAD/microsoft-authentication-library-for-dotnet/wiki/msal-net-2-released#migrating-from-adalnet-3x-or-4x-to-msalnet-2x), could this example be altered to reflect the changes?

From what I can tell, the only change in this would be changing the body of GetUserAccessTokenAsync to use cca.GetAccountsAsync() and checking the result for items, rather than using cca.Users. Or would you use cca.GetAccountAsync?

Anyways, I would submit a pull request, but with the new changes I am not able to get this sample to work (my cca.GetAccountsAsync() returns an empty IEnumerable; no clue why, and I can't find any documented issues on this on Stack Overflow or on the MSAL repo). I don't want to submit a PR for something I haven't been able to test!

Anyways I'm guessing

if (!cca.Users.Any()) throw new ServiceException(new Error

...
`
would need to change to

var accounts = await cca.GetAccountsAsync();`
if (!accounts.Any()) throw new ServiceException(new Error
...

in the GraphAuthProvider class.

If I can get the GetAccountsAsync to return properly, I'll try to put a pull request together.

Default port did not work, seemed to cause sign in to fail

Expected behavior: sample should work using the default port listed in the readme (44334)

Actual behavior: sample loads the home page, and upon entering my email to sign in, I am redirected to this url: "https://login.microsoftonline.com/login.srf". It seems like something is trying to be loaded, but it eventually stops. If I reenter that url, I am taken to the page "https://www.office.com/?auth=2".

My fix: Change the port in the project (launch and app settings files) and in the app registration's redirect url to "44328"

How I decided on this port: When the login.srf page redirected me to the office.com page, in the list of applications, in the category of "other", was an application called "graph explorer". This sounded like it could be relevant. When I clicked it, I was brought to localhost:44328/. So I figured that might be the port I should use. Then I applied my fix listed above, and the sample works.

SetBeforeAccess method doesn't exist

These two lines need to be updated as they don't seem to exist anymore.

            _cache.SetBeforeAccess(BeforeAccessNotification);
            _cache.SetAfterAccess(AfterAccessNotification);

Instead, they should be the following based on the latest NuGet package

            _cache.BeforeAccess = BeforeAccessNotification;
            _cache.AfterAccess = AfterAccessNotification;

Access user groups

How could I get access to user groups and do some proper authorisation with this sample app ?

Issues porting the sample logic to a fresh (razor) application

Hello,

Really cool sample first of all - it works quite well when I just clone and run it, and since I was looking to help automate some of my emailing it's exactly what I was looking for ๐Ÿ™‚

Your contributing section article link leads nowhere by the way, so sorry if this issue is not in the desired format.

I am having an issue with the login process, which is odd. I did the following:

I have a completely fresh .NET core application, created by selecting "Web" (not MVC, Razor Pages I think), including authentication.

I then initially added a Microsoft account, which worked fine for authentication and logs me in.

Then I looked at this sample, which runs great locally after creating an application id / secret in the portal, and it correctly links my full name from my account.

Wanting to port the sample logic to my app, I changed startup (see below, included outcommented microsoft account logic):

public class Startup
{
  public Startup(IConfiguration configuration)
  {
    Configuration = configuration;
  }

  public IConfiguration Configuration { get; }
  public const string ObjectIdentifierType = "http://schemas.microsoft.com/identity/claims/objectidentifier";
  public const string TenantIdType = "http://schemas.microsoft.com/identity/claims/tenantid";


  // This method gets called by the runtime. Use this method to add services to the container.
  public void ConfigureServices(IServiceCollection services)
  {
    services.AddDbContext<ApplicationDbContext>(options =>
      options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));

    services.AddIdentity<ApplicationUser, IdentityRole>()
      .AddEntityFrameworkStores<ApplicationDbContext>()
      .AddDefaultTokenProviders();

    //services.AddAuthentication().AddMicrosoftAccount(options =>
    //{
    //	options.ClientId = Configuration["Authentication:Microsoft:ApplicationId"];
    //	options.ClientSecret = Configuration["Authentication:Microsoft:Password"];
    //});

    services.AddAuthentication(sharedOptions =>
    {
      sharedOptions.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
      sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme;
      sharedOptions.DefaultChallengeScheme = OpenIdConnectDefaults.AuthenticationScheme;
    })
    .AddAzureAd(options => Configuration.Bind("AzureAd", options))
    .AddCookie();
    // This sample uses an in-memory cache for tokens and subscriptions. Production apps will typically use some method of persistent storage.
    services.AddMemoryCache();
    services.AddSession();

    // Add application services.
    //services.AddSingleton<IConfiguration>(Configuration);
    services.AddSingleton<IGraphAuthProvider, GraphAuthProvider>();
    services.AddTransient<IGraphSdkHelper, GraphSdkHelper>();

    services.AddMvc()
      .AddRazorPagesOptions(options =>
      {
        options.Conventions.AuthorizeFolder("/Account/Manage");
        options.Conventions.AuthorizePage("/Account/Logout");
      });

    // Register no-op EmailSender used by account confirmation and password reset during development
    // For more information on how to enable account confirmation and password reset please visit https://go.microsoft.com/fwlink/?LinkID=532713
    services.AddSingleton<IEmailSender, EmailSender>();
  }

  // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
  public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  {
    if (env.IsDevelopment())
    {
      app.UseDeveloperExceptionPage();
      app.UseBrowserLink();
      app.UseDatabaseErrorPage();
    }
    else
    {
      app.UseExceptionHandler("/Error");
    }

    app.UseStaticFiles();
    app.UseSession();
    app.UseAuthentication();
    app.UseMvc(routes =>
    {
      routes.MapRoute(
        name: "default",
        template: "{controller}/{action=Index}/{id?}");
    });
  }
}

I copied the AzureAD settings from my working sample, and changed the port to match the app, and copied the "helper" folder with all cs files, and the extensions files into the extensions folder, added the nuget packages required and run the application.

What happens is I go through the whole authentication flow, all the way up to registering external provider and then the application throws me back to the index page, without having authenticated.

Pointers to what I'm doing wrong, and how I can port your logic to an existing application? ๐Ÿ™‚

Authentication success, but after redirect to site Getting the error page - Azure app service

Hi All,
After authentication, the site is redirecting to error page. May i know what could be the cause. all the settings were made as per your guide.

Error.
An error occurred while processing your request.
Development Mode
Swapping to Development environment will display more detailed information about the error that occurred.

Development environment should not be enabled in deployed applications, as it can result in sensitive information from exceptions being displayed to end users. For local debugging, development environment can be enabled by setting the ASPNETCORE_ENVIRONMENT environment variable to Development, and restarting the application.

Thanks
Anuraj Rajagopal

Unable to get user photo

Hello,

I'm unable to get the user photo. I get the following error:

Code: AuthenticationError
Message: Error authenticating with resource

Inner error

Stack Tracke:

   at Microsoft.Graph.HttpProvider.SendAsync(HttpRequestMessage request, HttpCompletionOption completionOption, CancellationToken cancellationToken)
   at Microsoft.Graph.BaseRequest.SendRequestAsync(Object serializableObject, CancellationToken cancellationToken, HttpCompletionOption completionOption)
   at Microsoft.Graph.BaseRequest.SendStreamRequestAsync(Object serializableObject, CancellationToken cancellationToken, HttpCompletionOption completionOption)
   at MicrosoftGraphAspNetCoreConnectSample.Helpers.GraphService.GetPictureStream(GraphServiceClient graphClient, String email, HttpContext httpContext) in C:\code\aspnetcore-connect-sample\MicrosoftGraphAspNetCoreConnectSample\Helpers\GraphService.cs:line 99

Getting the user profile works fine.

Cheers

User not found in token cache

Getting the null in
var account = await _app.GetAccountAsync(userId);
How i will get the account value and How to store token in cache?

The cached _graphClient instance in GraphSDKHelper is not used

The _graphClient field in GraphSDK helper appears to be there in order to cache the reference between executions of the GetAuthenticatedClient method. Except that the private field is only ever referenced from this function, and is generated new for every single function call. Either the call needs to be changed to check it against null and then create the instance if null, or the variable can be moved from a field to a local function variable.

Code is not usable in a deployed web app.

The approach used in this sample is not feasible in a production environment with a deployed service. The redirect url is formed from a hard-coded base url ("https://localhost") in appsettings.json, which is not practical of course.

According to the MSAL docs the redirect url should be formed by extracting the base url from the http context at the time of the request. It's not clear, however, how to refactor the helper classes from the sample to do this, since ConfigureAzureOptions.Configure(), which is called at startup, uses the Authority string created in the call to ConfidentialClientApplicationBuilder.Create, which if you follow the docs example isn't called until a request, in options.Events.OnAuthorizationCodeReceived.

The reply address does not match the reply addresses configured for the application

I have configured an application via the portal (converged). I was running under a differen port though, so when settup up the URLS in the app registrations I changed them to match my port number...

Now I'm receiving this error after the flow is trying to connect back to my application. How can I debug this, or how do I know what is happening?

Additional technical information:
--
Correlation ID: 145d8f37-7229-4dce-8ace-c777e4aeef94
Timestamp: 2017-11-02 08:41:21Z
AADSTS50011: The reply address 'http://localhost:60761/signin-oidc' does not match the reply addresses configured for the application: '8b640f9d-e7d8-4c41-8a40-15069f5712ee'. More details: not specified

azureadconvergederror

Error when running application (single-tenant vs multi-tenant)

I run this app after filling in the details as instructed. I get this error after trying to Login

OpenIdConnectProtocolException: Message contains error: 'invalid_request', error_description: 'AADSTS50194: Application '{id}'({name} is not configured as a multi-tenant application. Usage of the /common endpoint is not supported for such applications created after '10/15/2018'. Use a tenant-specific endpoint or configure the application to be multi-tenant.

I did not see any instructions for this to be a multi-tenant app.

Client that uses custom API and Graph

For a client (web) application that needs to make requests to Graph and another API (e.g. myapi.azurewebsites.net), what is the best practice?

Should a client acquire two separate access tokens? One with the Graph audience and one for myapi.azurewebsites.net? Or, is there a way to generate a token with an audience of myapi.azurewebsites.net that has scopes for Graph?

Release version for production env

Hey, this sample you created is fantastic. I am developing something similar to this. I tried your sample app too. Can you please suggest me what alteration I must do to deploy this sample on production environment?
It would be really helpful.
Thankyou in advance.

User must sign in again after on hour

When running this sample, it looks like the user must sign in once per hour (maybe after hour of inactivity). I know that the Azure authentication token expires after one hour, so I guess that is related.

Is there some easy way to fix this? If I create a new application with Azure sign in the user is signed in a lot longer by default.

I have upgraded this sample to use Asp.Net Core 2.1, and I think it behaves the same as in version 2.0.

(Otherwise I think the sample is great :-)

GetPhoto works fine for user with global admin role but fails for normal users.

When I tried to get profile picture for the users, it works fine with the user who is Global admin. But it throws error for other users who are non admins.

Code: UnknownError

Inner error

StatusCode:Unauthorized

I have configured required scopes in the delegated permission.

User.Read User.ReadBasic.All

{ "aud": "https://graph.microsoft.com", "iss": "https://sts.windows.net/c7dd3e60-9fc4-40c1-8a22-b8d36677cee9/", "iat": 1523429419, "nbf": 1523429419, "exp": 1523433319, "acr": "1", "aio": "Y2NgYNCbzXVKcLOibutr1gUZhjknmj6s7ntrkFPQZjij0WDt+6cA", "amr": [ "pwd" ], "app_displayname": "XXX", "appid": "1dfb0546-7413-445a-beef-a2482e9aeb2e", "appidacr": "1", "e_exp": 262800, "ipaddr": "202.153.46.130", "name": "surendra", "oid": "f67b32d8-4b95-4dc0-9fd4-9ce2057027b1", "platf": "3", "puid": "10037FFEA8D411C2", "scp": "Directory.AccessAsUser.All Directory.ReadWrite.All Files.Read User.Read User.ReadBasic.All User.ReadWrite", "sub": "MAOmTQt1Jb7F1CV_BQxGnE_JQzSd9U6o5oOndydp_98", "tid": "c7dd3e60-9fc4-40c1-8a22-b8d36677cee9", "unique_name": "XXXX", "upn": "XXX", "uti": "Dr8llO2QfUm4BJEttG8qAA", "ver": "1.0" }

TokenNotFound

Since yesterday I can only login 1 time after restart the computer. If I restart the running project I get this error. http://prntscr.com/jfm64g
(Maybe only when expire)
"Maybe the server was restarted." Well it was but where's my new login page?

Any ideas of what may be causing it?

Application using http vs https

Auto "Sign In" User without Token

In testing, every time I reload the App in Visual Studio I'm redirected back to the MSFT Sign In dialog. My account is already "Signed In" so all I'm doing is having to click my Account which redirects me back to the App.

I get that is due to not having a token in memory, however is there anyway to auto login so I don't have to "click through" ?

Example Showing Azure AD Only Application

Are there any examples showing similar Auth/Graph access with Core and Azure AD Only app?

In my case I only want to login users for a given Work tenant, and don't care about the app being Converged.

Or what is the best way to restrict Auth to a given tenant? Would I still want to create a Converged App?

Thanks!

Unable to get access token

Hello,

I downloaded the aspnetcore-connect-sample and I was successfully connected to Azure active directory but I could not get access token to get user profile and photo. Below function returns "null".

var account = await _app.GetAccountAsync(userId);

Please find my application details.

  1. ASP.net core 3.0 mvc web application
  2. using Microsoft.Identity.Client (4.3.1)
  3. I am using visual studio in MAC

Please provide your suggestion to get the access token.

Access denied when trying to get mail messages

I'm able to get the profile information just fine from the sample. I'm adding code to get messages from the inbox. When I do the following:

var mailResults = await graphClient.Me.MailFolders.Inbox.Messages.Request()

I get access denied like so:

ServiceException: Code: ErrorAccessDenied
Message: Access is denied. Check credentials and try again.

If it's already authenticated, why am I getting invalid credentials with this?

Thanks!

ConfidentialClientApplication.AcquireTokenForClientAsync(IEnumerable<string>)' is obsolete

Error CS0619 'ConfidentialClientApplication.AcquireTokenForClientAsync(IEnumerable)' is obsolete: 'Use AcquireTokenForClient instead. See https://aka.ms/msal-net-3-breaking-changes' Kalisto C:\Users\NS-X\source\repos\LexisMedia\kalisto\Helper\SyncMailBoxHelper.cs 261 Active

This line is obsolete

var result = await _app.AcquireTokenSilentAsync(_scopes, account);

The profile picture is not loading and getting access denied error.

Hi Team,

Able to read the user profile details. But the profile picture is not loading and getting below
exception. Have set the readbasic and read properties as well.

Code: ErrorAccessDenied
Message: Access to OData is disabled.

Please help to figure it out.

Thanks,
Anuraj Rajagopal

Single tenant - Guest Account login error - Null Token

  1. Updated the GraphAuthProvider.cs for supporting single tenant.
    _app = ConfidentialClientApplicationBuilder.Create(azureOptions.ClientId)
    .WithClientSecret(azureOptions.ClientSecret)
    .WithTenantId(azureOptions.TenantId)
    .WithAuthority(AzureCloudInstance.AzurePublic, AadAuthorityAudience.AzureAdMyOrg)
    .WithRedirectUri(azureOptions.BaseUrl + azureOptions.CallbackPath)
    .Build();
    Azure App updated for Single Tenant:
    image

  2. From Azure Portal, Invited the Guest User.
    image

  3. Tried to login with Guest account, login url goes into loop.
    Debugging shows that getting the null in
    var account = await _app.GetAccountAsync(userId);

image

image

Any help to solve this issue?

Retrieve user groups in Startup.cs

Bug description
A clear and concise description of what the bug is.

Repro steps
I'm trying to modify the your sample to pull user group membership in Startup.cs class file so that I can add user groups as claims. But I could not make it to work. Is it something not possible or I'm doing something wrong? Can you please help me with sample code or pointers?
Thank you!

Expected behavior
A clear and concise description of what you expected to happen.

Screenshots
If applicable, add screenshots to help explain your problem.

Additional context
Add any other context about the problem here.

User.Identity.Name returning full name instead of email and photo returning 'ResourceNotFound'

Hi,

When I try the application for 'User.Identity.Name' I get full name instead of email. So I changed the ger users's email line to

email = email ?? User.FindFirst(Startup.UpnType)?.Value;

where
public const string UpnType = "http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn";

For GetPictureStream in the first catch I was getting Request_ResourceNotFound but nothing would happen so I added

else
{
    throw;
}

Then the second catch would work and I got the default image. I am not sure why v1.0 is not returning an image. Any ideas?

Support for signInAudience AzureADMyOrg or AzureADMultipleOrgs

I have a question! Until know it works for any account (AzureADMultipleOrgs --> common Endpoint). Do you know what need to be changed in the code so that it works? On the registration side I already changed it.

Many thanks for your help
Regards,
Joรซl

Supported account types issue

Where do i set supported account types? It's not an option when registering the application in Azure, and I don't see it in the manifest.

I can only get this example to run if i select "Accounts in any organizational directory", but I'd like to only allow internal users.

Issues integrating into existing Core project

Not sure if this is the right way to ask for help, but I could use a hand.

I have a project located at https://github.com/ZeroPKI/OAuthGateway where I have a fork of this project up and running, and a second project running .NET Core 2.1.

Anytime MSAL returns the authentication it results in error. Live demo here:
https://us-sw-zeropki-oauthgateway.azurewebsites.net/

I've compared each project line-by-line, and even upgraded this sample up to ASP.NET Core 2.1, and replaced the ASPNET.ALL library with ASPNET.NET. Any assistance or guidance is appreciated.

User.Identity.Name

Any idea why User.Identity.Name would be null? I was previously using Azure AD only authentication out of the box from Microsoft. I have no switched over to using this sample with the Graph API and the /common/v2.0 library. Feel like i've missed something somewhere but not sure where to start?

Configuring for single tenant

I've been trying to configure the sample for a single tenant but I'm hitting a brick wall. If I go into App Registration (Preview) - Authentication, under Supported account types, when I register the application following the guidelines its allowing users in any organization and doesn't show the option to configure for single organization. It advises editing the manifest, but after attempting this I'm unsure as to what part of the manifest to edit, and how.

I've tried a new registration through the portal and I'm able to set the Supported account types to 'Accounts in this organizational directory only', however when I run the app, after I log in, I get an error message advising me to switch the environment to development. However, the launchSettings.json show the app is already in development. As a result I have no way of debugging the issue.

If I switch the account type to any organizational directory I get no error still. I have specified the tenant in the Authority. Any ideas?

Transient creation of GraphServiceClient

Bug description

Maybe I'm misreading something, but the GraphSdkHelper violates the first paragraph of the documentation on how to create a GraphServiceClient.

The documentation states the following:

You can use a single client instance for the lifetime of the application.

However the HomeController
seems to create a new GraphServiceClient with every call to the Index route.

Additional context

Might be related to the issue #4 .

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.