none
First Graph Sample SendMail attempt getting HTTP forbidden response RRS feed

  • Question

  • Hi, I went to the Microsoft Graph Quick Start site: (https://developer.microsoft.com/en-us/graph/quick-start?appID=3f1b1b72-c99c-401b-a0b0-669e11a48190&appName=AndyFoolAround%20App&redirectUrl=http://localhost:55065&platform=option-dotnet) and registered my first sample application with an Id and application secret provided by the portal.

    Then I downloaded the MVC C# <g class="gr_ gr_75 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace" data-gr-id="75" id="75">csproject</g> and the zip file contains <g class="gr_ gr_121 gr-alert gr_gramm gr_inline_cards gr_run_anim Grammar multiReplace" data-gr-id="121" id="121">an Web.config</g> file with the updated clientId and secret populated.  According to the sample instruction, this sample supposes to send Email.

    Then I rebuilt the project since some of the NuGet packages are not available.  I did not choose to update my NuGet packages to the latest level since the sample might require the exact older NuGet <g class="gr_ gr_215 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace" data-gr-id="215" id="215">pacakges</g> as dependencies.

    Then I started in VStudio to launch my web browser so it connects via the redirect URI and I filled in an O365 valid account.  The first time I signed on, the web page shows that it would grant permissions for this application to access.  I hit OK since I am expecting this sample application should have permission to act on my O365 behalf.  The sign-in was successful.  Then I filled in with an internet Recipient address to test this sample application.  The send mail application using the Graph API failed.  I stepped through the code to see what it did.

    It was failing when SendAsSync was called:

                using (var client = new HttpClient())
                {
                    using (var request = new HttpRequestMessage(HttpMethod.Post, Settings.SendMessageUrl))
                    {
                        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
                        request.Content = new StringContent(JsonConvert.SerializeObject(sendMessageRequest), Encoding.UTF8, "application/json");
                        using (HttpResponseMessage response = await client.SendAsync(request))
                        {
                            if (response.IsSuccessStatusCode)
                            {
                                sendMessageResponse.Status = SendMessageStatusEnum.Sent;
                                sendMessageResponse.StatusMessage = null;
                            }
                            else
                            {
                                sendMessageResponse.Status = SendMessageStatusEnum.Fail;

    The response captured was:

    - response {StatusCode: 403, ReasonPhrase: 'Forbidden', Version: 1.1, Content: System.Net.Http.StreamContent, Headers:
    {
      Transfer-Encoding: chunked
      request-id: 07e2a143-265c-44bf-8fd5-c4058192d25b
      client-request-id: 07e2a143-265c-44bf-8fd5-c4058192d25b
      x-ms-ags-diagnostic: {"ServerInfo":{"DataCenter":"West US","Slice":"SliceB","ScaleUnit":"001","Host":"AGSFE_IN_0","ADSiteName":"WST"}}
      Duration: 244.818
      Cache-Control: private
      Date: Fri, 14 Apr 2017 20:40:53 GMT
      Content-Type: application/json
    }} System.Net.Http.HttpResponseMessage

    The request header and content were what the application specified as I did not modify anything:

    - Content {System.Net.Http.StringContent} System.Net.Http.HttpContent {System.Net.Http.StringContent}
    - Headers {Content-Type: application/json; charset=utf-8
    Content-Length: 2239
    } System.Net.Http.Headers.HttpContentHeaders
    + Allow {} System.Collections.Generic.ICollection<string> {System.Net.Http.Headers.HttpHeaderValueCollection<string>}
    + ContentDisposition null System.Net.Http.Headers.ContentDispositionHeaderValue
    + ContentEncoding {} System.Collections.Generic.ICollection<string> {System.Net.Http.Headers.HttpHeaderValueCollection<string>}
    + ContentLanguage {} System.Collections.Generic.ICollection<string> {System.Net.Http.Headers.HttpHeaderValueCollection<string>}
    ContentLength 2239 long?
    + ContentLocation null System.Uri
    ContentMD5 null byte[]
    ContentRange null System.Net.Http.Headers.ContentRangeHeaderValue
    + ContentType {application/json; charset=utf-8} System.Net.Http.Headers.MediaTypeHeaderValue
    Expires null System.DateTimeOffset?
    LastModified null System.DateTimeOffset?

    -----

    If I updated the bundled Microsoft.IdentityModel.Clients.ActiveDirectory from 2.19.208020213 to v3.13.9

    then the solution would not even compile with error.

    1>------ Build started: Project: UnifiedApiConnect, Configuration: Debug Any CPU ------
    1>C:\Graphs\GraphPokerSample1\Update1\UnifiedApiConnect\Controllers\HomeController.cs(43,39,43,65): error CS1061: 'AuthenticationContext' does not contain a definition for 'GetAuthorizationRequestURL' and no extension method 'GetAuthorizationRequestURL' accepting a first argument of type 'AuthenticationContext' could be found (are you missing a using directive or an assembly reference?)

    So I presume the SDK sample is not written to support the latest Identity Client API.

    Could Graph experts in this forum provide some assistance on what steps I should take to get something basic to work as I am developing an application taking <g class="gr_ gr_1179 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace" data-gr-id="1179" id="1179">advantave</g> of the Graph <g class="gr_ gr_1193 gr-alert gr_gramm gr_inline_cards gr_run_anim Punctuation multiReplace" data-gr-id="1193" id="1193">infrastructure.</g>

    Friday, April 14, 2017 10:07 PM

All replies

  • I logged on <g class="gr_ gr_13 gr-alert gr_gramm gr_inline_cards gr_run_anim Punctuation only-del replaceWithoutSep" data-gr-id="13" id="13">to:</g> https://apps.dev.microsoft.com/#/appList

    and I saw the sample app has delegated permission set to User.Read so I updated my app permission with Mail.Send and Mail.Send.Shared permissions.  Then I tried to retest my <g class="gr_ gr_248 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace" data-gr-id="248" id="248">webrequest</g> and I set a breakpoint at:

                var authResult = await authContext.AcquireTokenByAuthorizationCodeAsync(
                    Request.Params["code"],                                         // the auth 'code' parameter from the Azure redirect.
                    loginRedirectUri,                                               // same redirectUri as used before in Login method.
                    new ClientCredential(Settings.ClientId, Settings.ClientSecret), // use the client ID and secret to establish app identity.
                    Settings.O365UnifiedAPIResource);

                // Save the token in the session.
                Session[SessionKeys.Login.AccessToken] = authResult.AccessToken;

    The AccessToken was captured and pasted into the http://jwt.calebb.net/ and the <g class="gr_ gr_460 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace" data-gr-id="460" id="460">scp</g> remains to be User.Read even though I have granted the app with additional Send permissions.  So I have no idea why the permission was not granted. 

    Saturday, April 15, 2017 7:04 AM
  • After searching all over the place on the Internet, I discovered the solution.

    The problem is described in this article:  http://stackoverflow.com/questions/42013466/microsoftgraph-oauth2-scope

    It was a pretty lame authorization model as it would prompt for the initial permission on the first sign-in of the application so even if I changed the permission after the first sign-in, the new permission won't be used.  So the magic touch is that I recreated with a new application Id and then set up the new permission properly before the first sign-in.

    The other way is to update the application to prompt for the permission granting process each time the application performs its login.

    Sunday, April 16, 2017 8:03 AM