【问题标题】:Microsoft.Graph.ServiceException: Code: methodNotAllowedMicrosoft.Graph.ServiceException:代码:methodNotAllowed
【发布时间】:2021-06-16 04:37:00
【问题描述】:

将以下请求发送给我的 b2c 租户后,我得到了 400。详情见下文:

Microsoft.Graph.ServiceException:代码:methodNotAllowed 消息:此 URL 不支持该方法。

我需要重置用户密码,所以我按照这里描述的:https://docs.microsoft.com/en-us/graph/api/passwordauthenticationmethod-resetpassword?view=graph-rest-beta&tabs=csharp

这是我的代码:

public async Task<string> ResetPassword(string userId)
        {
            var newPassword = Helpers.PasswordHelper.GenerateNewPassword(4, 8, 4);
            var result = await graphClient
                .Users[userId]
                .Authentication.PasswordMethods["{passwordAuthenticationMethod-id}"]
                .ResetPassword(newPassword, null)
                .Request()
                .PostAsync();
            return result.NewPassword;
        }

我添加到项目中的包

<Project Sdk="Microsoft.NET.Sdk.Web">
  <PropertyGroup>
    <TargetFramework>netcoreapp3.1</TargetFramework>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.Graph.Auth" Version="1.0.0-preview.4" />
    <PackageReference Include="Microsoft.Graph.Beta" Version="0.39.0-preview" />
    <PackageReference Include="Microsoft.Identity.Client" Version="4.13.0" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.2" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0" />
  </ItemGroup>
</Project>

我做错了什么?

【问题讨论】:

  • 不允许的方法是 405 :P
  • 用户 id 是正确的用户 id,而不是奇怪的东西吗?我想您所遇到的一种解释是 api 将所有内容转换为端点 URI,将用户 ID 替换为路径,并最终匹配不接受帖子的内容。但只是一个想法。
  • 您登录的帐户是否具有“全局管理员”或“身份验证管理员”或“特权身份验证管理员”角色?
  • 怎么样?您的问题解决了吗?

标签: c# .net-core microsoft-graph-api azure-ad-b2c


【解决方案1】:

不建议使用 Microsoft Graph Beta 版本:

如果您想更改用户的密码,可以尝试使用 Microsoft Graph API 来完成,只需尝试下面的简单控制台应用即可:

    using Newtonsoft.Json;
    using System;
    using System.Collections.Generic;
    using System.IO;
    using System.Net;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using System.Threading.Tasks;
    
    namespace graphsdktest
    {
        class Program
        {
    
            public static async Task<string> GetAccessToken()
            {
    
                using (var client = new HttpClient())
                {
                    var clientId = "<app id>";
                    var clientSecret = "<app secret>";
                    var tenantID = "<tenant id>";
                    var adminUserName = "<b2c admin user account>";
                    var password = "<b2c admin user password>";
    
                    var tokenUrl = @"https://login.microsoftonline.com/" + tenantID + "/oauth2/v2.0/token";
                    client.BaseAddress = new Uri(tokenUrl);
                    
                    client.DefaultRequestHeaders.Accept.Clear();
                    client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    
                    List<KeyValuePair<string, string>> postData = new List<KeyValuePair<string, string>>();
                    postData.Add(new KeyValuePair<string, string>("grant_type", "password"));
                    postData.Add(new KeyValuePair<string, string>("client_id", clientId));
                    postData.Add(new KeyValuePair<string, string>("client_secret", clientSecret));
                    postData.Add(new KeyValuePair<string, string>("scope", "openid"));
                    postData.Add(new KeyValuePair<string, string>("username", adminUserName));
                    postData.Add(new KeyValuePair<string, string>("password", password));
    
                    FormUrlEncodedContent requestBody = new FormUrlEncodedContent(postData);
                  
                    var request = await client.PostAsync(tokenUrl, requestBody).ConfigureAwait(false);
                    var response = await request.Content.ReadAsStringAsync();
                    var responseData = JsonConvert.DeserializeObject(response);
                  
                    return ((dynamic)responseData).access_token;
                }
            }
            static void Main(string[] args)
            {
                var accessToken = GetAccessToken().GetAwaiter().GetResult();
    
                var userID = "<target user id>";
                var newPass = "<new password>";
    
                var requstURL = @"https://graph.microsoft.com/v1.0/users/" + userID;
    
                var httpWebRequest = (HttpWebRequest)WebRequest.Create(requstURL);
                httpWebRequest.ContentType = "application/json";
                httpWebRequest.Headers.Add("Authorization", "Bearer " + accessToken);
                httpWebRequest.Method = "PATCH";
    
                using (var streamWriter = new StreamWriter(httpWebRequest.GetRequestStream()))
                {
                string json = "{\"passwordProfile\":{\"forceChangePasswordNextSignIn\":false,\"password\":\"" + newPass + "\"}}";
    
                    streamWriter.Write(json);
                }
    
                var httpResponse = (HttpWebResponse)httpWebRequest.GetResponse();
    
                //if code is 204 means request has been accepted, change password successfully
                Console.WriteLine((int)httpResponse.StatusCode);
            }
    }

}

您需要授予您的应用程序的权限:

有关此 API 的更多信息,请参阅this official doc

【讨论】:

  • 用户使用新密码登录后能否修改密码?
  • 如果希望用户登录后设置新密码,可以将json中forceChangePasswordNextSignIn的值设置为true
  • 非常感谢。这是我知道的事情,不知道在哪里可以找到正确的信息来测试你发布的代码,所以你能确认这是否正确吗?我会尝试添加图片
  • 顺便说一句,我看不到您发布的权限。
【解决方案2】:

我通过将角色 User Administrator 分配给我的 b2c 应用程序并生成了一个秘密,以便您可以使用它来配置您的 C# 应用程序,从而成功地使用 SDK 进行 Graph API 调用。

{
  "appSettings": {

    // MAKE SURE THESE REPRESENT YOUR TENANT SETTINGS
    "TenantId": "XXXXX.onmicrosoft.com",
    "AppId": "2a4c5942-7156-4fce-b524-XXXXXXXXX",
    "ClientSecret": "7746Dj-_h4rrK-XXXXXXXXXX",
  }
}

而更新密码的代码是:

public async Task<string> UpdateUserPassword(string userId)
{
    var password = Helpers.PasswordHelper.GenerateNewPassword(4, 8, 4);
    var user = new User
    {
        Id = userId,
        PasswordProfile = new PasswordProfile
        {
            Password = password,
            ForceChangePasswordNextSignIn = false
        },
        PasswordPolicies = "DisablePasswordExpiration"

    };

    await graphClient
        .Users[userId]
        .Request()
        .UpdateAsync(user);

    return password;
}

但是,我设置了ForceChangePasswordNextSignIn = false b2c 在第一次使用它登录后不会要求用户更改密码。如果您将其设置为true,我将无法登录。我正在使用自定义策略进行登录/注册。有什么想法吗?

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-09
    • 2019-01-31
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多