Graph API- Обновить токен — неверный запрос 400

#c# #azure #azure-active-directory #microsoft-graph-api #azure-ad-graph-api

#c# #azure #azure-active-directory #microsoft-graph-api #azure-ad-graph-api

Вопрос:

Цель — использовать Graph API для отправки электронной почты. Я могу получить токен авторизации, используя приведенный ниже код — https://login.microsoftonline.com/Some_Tenant_ID/oauth2/v2.0/authorize?client_id=SOME_Client_IDamp;response_type=codeamp;redirect_uri=https://localhostamp;response_mode=queryamp;scope=offline_access user.read mail.readamp;state=12345

Область действия user.read и mail.send с автономным доступом. Теперь, используя этот код авторизации, я хочу получить токен обновления. Насколько я понимаю, это должно работать без каких-либо проблем, но по какой-то причине код прерывается в этой строке var httpResponse = (HttpWebResponse)request.GetResponse(); , и я не уверен, почему.

Ошибка кода исключения 400 неверный запрос. мой вывод на консоль.

введите описание изображения здесь

Может ли кто-нибудь помочь мне здесь и есть ли другой способ получить токен доступа и / или токен обновления из токена авторизации. конечная цель — отправить электронное письмо из graph API.

 string tokenUrl = "https://login.microsoftonline.com/myAppTenantID/oauth2/token";
//string tokenUrl = "https://login.microsoftonline.com/myAppTenantID/oauth2/v2.0/token"; I have tried this URL too
string grant_type= "authorization_code";
string ClientID = "MyAppClientID";
string Auth_Code = "My Auth Code";
string RedirectURI = "https://localhost";
string ClientSecret = "my App secret";
Dictionary<string, string> res_dic = null;
string TargetURL = String.Format(tokenUrl);
var request = (System.Net.HttpWebRequest)WebRequest.Create(TargetURL);
request.ContentType = "application/x-www-form-urlencoded";
string RefreshToken = null;


string requestBody = String.Format(@"client_id={0}amp;scope=user.read mail.readamp;code={1}amp;redirect_uri={2}amp;grant_type=authorization_codeamp;client_secret={3}", ClientID, Auth_Code,RedirectURI, ClientSecret);
request.Method = "POST";
using (var streamwriter = new StreamWriter(request.GetRequestStream()))
{
    Console.WriteLine("stage 0....");
    streamwriter.Write(requestBody);
    streamwriter.Flush();
    streamwriter.Close();
}
try
{
    Console.WriteLine("stage 1....");
    //Console.WriteLine("prting response"  (HttpWebResponse)request.GetResponse());
    var httpResponse = (HttpWebResponse)request.GetResponse();
    Console.WriteLine("Stage 2....");
    using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
    {
        Console.WriteLine("Stage 3");
        string Result = streamReader.ReadToEnd();
        string StatusCode = httpResponse.StatusCode.ToString();
        res_dic = JsonConvert.DeserializeObject<Dictionary<string, string>>(Result);
    }
}
catch (WebException ex)
{
    Console.WriteLine("stage 4");
    string ErrorMessage = ex.Message.ToString();
    Console.WriteLine(ErrorMessage);
}
RefreshToken = res_dic["refresh_token"].ToString();

}
 

Ответ №1:

Это лучше для отладки для получения полного сообщения об ошибке, есть много ситуаций, когда возникает эта ошибка.

Область действия в вашем коде необходимо добавить offline_access , поскольку refresh_token она будет предоставлена только в том случае, если offline_access запрошена область действия.

Вы могли бы использовать SDK. Пример кода здесь:

 string[] scopes = new string[] { "", "" };

IConfidentialClientApplication app = ConfidentialClientApplicationBuilder
    .Create(clientId)
    .WithRedirectUri(redirectUri)
    .WithClientSecret(clientSecret)
    .WithAuthority(authority)
    .Build();

AuthorizationCodeProvider auth = new AuthorizationCodeProvider(app, scopes);

GraphServiceClient graphServiceClient = new GraphServiceClient(new DelegateAuthenticationProvider(async (requestMessage) => {

    // Retrieve an access token for Microsoft Graph (gets a fresh token if needed).
    var authResult = await app.AcquireTokenByAuthorizationCode(scopes, auth_code).ExecuteAsync();

    // Add the access token in the Authorization header of the API request.
    requestMessage.Headers.Authorization = new AuthenticationHeaderValue("Bearer", authResult.AccessToken);
    
})
);
 

И этот API используется для отправки почты, вам нужно сначала добавить Mail.Send разрешение.

 var message = new Message
{
    Subject = "Meet for lunch?",
    Body = new ItemBody
    {
        ContentType = BodyType.Text,
        Content = "The new cafeteria is open."
    },
    ToRecipients = new List<Recipient>()
    {
        new Recipient
        {
            EmailAddress = new EmailAddress
            {
                Address = "fannyd@contoso.onmicrosoft.com"
            }
        }
    },
    CcRecipients = new List<Recipient>()
    {
        new Recipient
        {
            EmailAddress = new EmailAddress
            {
                Address = "danas@contoso.onmicrosoft.com"
            }
        }
    }
};

var saveToSentItems = false;

await graphClient.Me
    .SendMail(message,saveToSentItems)
    .Request()
    .PostAsync();
 

Комментарии:

1. Привет, @Pamela, код SDK, которым вы поделились, предназначен для Java, для C # AuthorizationCodeProvider не принимает «Auth code» в качестве параметра. здесь — docs.microsoft.com/en-us/graph/sdks /. … А также я уже использую тег «Offline_access» при запросе кода аутентификации.

2. Извините, @rajan.sngh. Я редактирую код SDK для C #, здесь используется «auth_code» app.AcquireTokenByAuthorizationCode(scopes, auth_code) .