Jump to content

Officeapi

Members
  • Content Count

    19
  • Joined

  • Last visited

Everything posted by Officeapi

  1. I have a delphi desktop application and would like to use Graph API to get inforamation from Office 365. I registered the app in Entra. I got the access token, and when I tried to use the token to get user profile (https://graph.microsoft.com/v1.0/me), I got the error message 'HTTP/1.1 401 Unauthorized'. When I registered the app in Entra, the permission 'User.Read' is enabled under Graph. And also when the token is generated, the scope 'User.Read' is also set. When I run test in Postman with the token I get, I have the response with 200 OK. Here is the code to call Graph api: RESTClient.BaseURL := FConnection.RESTEndPoint; // https://graph.microsoft.com RESTListResGroupRequest.Resource := 'v1.0/me'; RESTListResGroupRequest.Params.Clear; RESTListResGroupRequest.Params.AddItem('Authorization', 'Bearer ' + FConnection.AuthToken, TRESTRequestParameterKind.pkHTTPHEADER, [poDoNotEncode]); RESTListResGroupRequest.Params.AddItem('Content-Type', 'application/json', TRESTRequestParameterKind.pkHTTPHEADER); RESTListResGroupRequest.ExecuteAsync; What could be the problem?
  2. It turns out that TRESTResponse may have some bug. Remember the 'ContentLength' is 348, and 'Content' is empty? After encode the 'RawBytes' of the response, I can see the profile content. For some unknown reason, TRESTResponse ignores the content. Thanks for all the replies.
  3. I created TRESTClient/Request in the code, and used seperate Clients. Still got JSONValue null. Is it possible that TRESTClient doesn't work in some situation?
  4. I don't have setting 'Accept'. After I added req.AddParameter('Accept', ctAPPLICATION_JSON, pkHTTPHEADER, [TRESTRequestParameterOption.poDoNotEncode]); the JSONValue is still null. Just check the component, there is setting for Accept: 'application/json, text/plain; q=0.9, text/html;q=0.8,'
  5. Here are the values I got during debug: RESTProfileResponse.Content : '' RESTProfileResponse.ContentLength : 348 RESTProfileResponse.ContentType : 'application/json;odata.metadata=minimal;odata.streaming=true;IEEE754Compatible=false' RESTProfileResponse.ContentEncoding : '' RESTProfileResponse.FullRequestURI : 'https://graph.microsoft.com/v1.0/me' RESTProfileResponse.Headers : (nil, $5A528A0, #$D#$A, nil, 0, ',', '"', '=', [soWriteBOM,soTrailingLineBreak,soUseLocale]) RESTProfileResponse.JSONText : '' RESTProfileResponse.JSONValue : nil RESTProfileResponse.Observers : ($120E3090, TComponent.GetObservers$ActRec($120FFAB4) as TObservers.TCanObserveEvent, TComponent.GetObservers$ActRec($120FFAB0) as TObservers.TObserverAddedEvent) RESTProfileResponse.RootElement : '' RESTProfileResponse.StatusCode : 200
  6. I used Charles Proxy to check the request/response for the GraphAPI call from my code (/v1.0/me), and it actually got my profile. But in the Delphi code, the he JSONValue of the response is nil. Here is the code to get the response: FieldRawResponse.Text := TJSON.Format(RESTListResGroupResponse.JSONValue); I also check that RESTListResGroupResponse.content is empty too. Here is the info I get from Charles Proxy
  7. Thanks for the reply. After I used seperate TRESTClient for Graph api call, I don't have 401 error anymore. Now the response has StatusCode 200. However, the JSONValue of the response is nil. I only want to get login user profile (https://graph.microsoft.com/v1.0/me), and the delegated permissions are in my first post. The scope for Access Token is: RESTTokenRequest.Params.AddItem('scope', 'IMAP.AccessAsUser.All Mail.Read Mail.ReadWrite Mail.Send offline_access openid POP.AccessAsUser.All profile User.Read Mail.Read', TRestRequestParameterKind.pkREQUESTBODY); I believe 'User.Read' is the only permission actually needed. What we have are more than enough. When I used the same token in Postman, I can get my profile. The response is also in my first post.
  8. Thanks for the update. I tried with RestClient.AddAuthParameter, now the error became 'HTTP1.1 400 Bad Request'.
  9. I switched the 'Clear' and 'Resource' lines, and used 'AddParameter' as well. I saved the access token in 'FConnection.AuthToken'. Still the same result (401 unauthorized).
  10. I also tried to use Charles Proxy to check the request/response for Graph API (GET https://graph.microsoft.com/v1.0/me), I got the follow error in Charles Proxy window: { "error": { "code": "InvalidAuthenticationToken", "message": "CompactToken parsing failed with error code: 80049217", "innerError": { "date": "2023-11-06T19:13:00", "request-id": "65e9c9d2-68ca-4081-bcfa-63a7cc1a1fa4", "client-request-id": "65e9c9d2-68ca-4081-bcfa-63a7cc1a1fa4" } } } I also copied the access token, and used it in Postman, it still worked. I am using Delphi 11. What could be the problem?
  11. I have tried to mimic what Postman sent. But still got the same error. Here is my code RESTClient.BaseURL := FConnection.RESTEndPoint; // https://graph.microsoft.com RESTProfileRequest.Method := TRESTRequestMethod.rmGet; RESTProfileRequest.Resource := 'v1.0/me'; RESTProfileRequest.Params.Clear; RESTProfileRequest.Params.AddItem('Authorization', 'Bearer ' + FConnection.AuthToken, TRESTRequestParameterKind.pkHTTPHEADER, [poDoNotEncode]); RESTProfileRequest.Params.AddItem('Content-Type', 'application/json', TRESTRequestParameterKind.pkHTTPHEADER); RESTProfileRequest.Params.AddItem('User-Agent', 'PostmanRuntime/7.34.0', TRESTRequestParameterKind.pkHTTPHEADER); RESTProfileRequest.Params.AddItem('Accept', '*/*', TRESTRequestParameterKind.pkHTTPHEADER); // RESTProfileRequest.Params.AddItem('Postman-Token', 'e08693a1-7ca4-463f-b83f-bd3c7878c798', TRESTRequestParameterKind.pkHTTPHEADER); RESTProfileRequest.Params.AddItem('Host', 'graph.microsoft.com', TRESTRequestParameterKind.pkHTTPHEADER); RESTProfileRequest.Params.AddItem('Accept-Encoding', 'gzip, deflate, br', TRESTRequestParameterKind.pkHTTPHEADER); RESTProfileRequest.Params.AddItem('Connection', 'keep-alive', TRESTRequestParameterKind.pkHTTPHEADER); RESTProfileRequest.ExecuteAsync;
  12. Here is the code to call Graph api: RESTClient.BaseURL := FConnection.RESTEndPoint; // https://graph.microsoft.com RESTProfileRequest.Method := TRESTRequestMethod.rmGet; RESTProfileRequest.Resource := 'v1.0/me'; RESTProfileRequest.Params.Clear; RESTProfileRequest.Params.AddItem('Authorization', 'Bearer ' + FConnection.AuthToken, TRESTRequestParameterKind.pkHTTPHEADER, [poDoNotEncode]); RESTProfileRequest.Params.AddItem('Content-Type', 'application/json', TRESTRequestParameterKind.pkHTTPHEADER); RESTProfileRequest.ExecuteAsync; I am stuck here for several days. Any suggestion will be appreciated.
  13. I did check Microsoft Ignite on how to get user profile. What I need is a sign-in user getting his own profile, not the application type. If you check my first post, all permissions are delegated. Maybe my code used it wrong? It is a desktop application. I did get the access token. I copied the token to Postman, it worked with GET https://graph.microsoft.com/v1.0/me Here is how I get access token (for the scope, I just list all permissions in Entra setting, I believe the one actually needed is User.Read): RestClient.BaseURL := FConnection.TokenEndPoint; //'https://login.microsoftonline.com/' + FConnection.TenantId + '/oauth2/v2.0/token' RESTTokenRequest.Method := TRESTRequestMethod.rmPOST; RESTTokenRequest.Params.Clear; RESTTokenRequest.Params.AddItem('tenant', FConnection.TenantId, TRestRequestParameterKind.pkQUERY); RESTTokenRequest.Params.AddItem('client_id', FConnection.ClientId, TRestRequestParameterKind.pkQUERY); RESTTokenRequest.Params.AddItem('grant_type', 'authorization_code', TRestRequestParameterKind.pkREQUESTBODY); RESTTokenRequest.Params.AddItem('client_id', FConnection.ClientId, TRestRequestParameterKind.pkREQUESTBODY); RESTTokenRequest.Params.AddItem('code', FConnection.AuthCode, TRestRequestParameterKind.pkREQUESTBODY); RESTTokenRequest.Params.AddItem('scope', 'IMAP.AccessAsUser.All Mail.Read Mail.ReadWrite Mail.Send offline_access openid POP.AccessAsUser.All profile User.Read Mail.Read', TRestRequestParameterKind.pkREQUESTBODY); RESTTokenRequest.Params.AddItem('redirect_uri', FConnection.RedirectURL, TRestRequestParameterKind.pkREQUESTBODY); //'https://login.microsoftonline.com/common/oauth2/nativeclient' RESTTokenRequest.Params.AddItem('response_type', 'code', TRestRequestParameterKind.pkREQUESTBODY); RESTTokenRequest.ExecuteAsync;
  14. I tried with 'Execute', and it didn't work (still 401 Unauthorized). I also tried to use Mitmweb to capture the actual request. However, it only captured the request for the first step (log in and get authorization code). The requests for second step (use the code to get access token), and the third step (use access token to get user profile) were not captured. Although I did get the access token from the second step. I set the proxy server address http://localhost, and port 8080. Did I miss something?
  15. Thanks for the reply. I checked during debug, if the method is not given, it will be rmGet. I also tried the scope 'https://graph.microsoft.com/.default', same result.
  16. Thanks for the reply. I got the authorization code first, then used the code to get the token with the parameters 'tenant', 'client_id', 'grant_type', 'code', 'scope', 'redirect_uri' and 'response_type'. Here is the code for the scope: RESTTokenRequest.Params.AddItem('scope', 'openid profile offline_access Mail.Read Mail.Send User.Read', TRestRequestParameterKind.pkREQUESTBODY);
×