如何使用Microsoft帐户身份验证从UWP向我的.NET核心应用程序发出请求

时间:2016-07-08 07:20:55

标签: asp.net-core uwp office365api

更新

网络端的一些代码

startup.cs

<form id="formLogin" action="./login.do" method="POST">
    <div id="wrap" style="padding-top:30px;">
        <div style="width:350px; height:80px; font-family:Tahoma; font-size:35px; font-weight:bold; margin:0 auto;">
            Login Page!
        </div>
        <div style="width:350px; height:40px; margin:0 auto;">
            <div style="width:30px; float:left;">&nbsp;</div>
            <div style="font-family:Tahoma; font-size:15px; width:65px; float:left; margin-right:10px; text-align:left; padding-top:6px;">
                Username
            </div>
            <div style="font-size:15px; width:210px; float:left;">
                <input type="text" id="textAccount" name="textAccount" style="width:206px; height:26px;">
            </div>
        </div>
        <div style="width:350px; height:50px; margin:0 auto;">
            <div style="width:30px; float:left;">&nbsp;</div>
            <div style="font-family:Tahoma; font-size:15px; width:65px; float:left; margin-right:10px; text-align:left; padding-top:6px;">
                Password
            </div>
            <div style="font-size:15px; width:210px; float:left;">
                <input type="password" id="textPass" name="textPass" style="width:206px; height:26px;">
            </div>
        </div>
        <div style="width:280px; height:30px; margin:0 auto;">
            <div style="font-size:15px; width:210px; float:right; text-align:right; padding-right:0px;">
                <input id="submitSend" type="submit" value="Sing in" style="background:#DDDDDD; border:1px solid; height:24px;">
            </div>
        </div>
        <div style="width:450px; height:20px; margin:0 auto;">
        </div>
</form>

HomeController.cs

        app.UseOAuthAuthentication(new OAuthOptions()
        {
            AuthenticationScheme = "Microsoft-AccessToken",
            DisplayName = "MicrosoftAccount-AccessToken",
            ClientId = {CliendID},
            ClientSecret = {ClientSecret},
            CallbackPath = new PathString("/signin-microsoft-token"),
            AuthorizationEndpoint = MicrosoftAccountDefaults.AuthorizationEndpoint,
            TokenEndpoint = MicrosoftAccountDefaults.TokenEndpoint,
            UserInformationEndpoint = MicrosoftAccountDefaults.UserInformationEndpoint,
            Scope = { "https://graph.microsoft.com/user.read" },
            SaveTokens = true,
            Events = new OAuthEvents()
            {
                OnCreatingTicket = async context =>
                {
                    var request = new HttpRequestMessage(HttpMethod.Get, context.Options.UserInformationEndpoint);
                    request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);
                    request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                    var response = await context.Backchannel.SendAsync(request, context.HttpContext.RequestAborted);
                    response.EnsureSuccessStatusCode();

                    var user = JObject.Parse(await response.Content.ReadAsStringAsync());

                    var identifier = user.Value<string>("id");
                    if (!string.IsNullOrEmpty(identifier))
                    {
                        context.Identity.AddClaim(new Claim(
                            ClaimTypes.NameIdentifier, identifier,
                            ClaimValueTypes.String, context.Options.ClaimsIssuer));
                    }

                    var userName = user.Value<string>("displayName");
                    if (!string.IsNullOrEmpty(userName))
                    {
                        context.Identity.AddClaim(new Claim(
                            ClaimTypes.Name, userName,
                            ClaimValueTypes.String, context.Options.ClaimsIssuer));
                    }

                    var email = user.Value<string>("userPrincipalName");
                    if (!string.IsNullOrEmpty(email))
                    {
                        context.Identity.AddClaim(new Claim(
                            ClaimTypes.Email, email,
                            ClaimValueTypes.Email, context.Options.ClaimsIssuer));
                    }
                }
            }
        });

我可以使用像这样的代码检索用户的令牌

    [Authorize]
    public string GetInfo()
    {
        return "Hello world!";
    }

但是如何使用令牌向我的.NET Core Web应用程序的API发出请求,该应用程序托管在azure上?

我试过这些

        string MicrosoftClientID = {ClientID};
        string MicrosoftCallbackURL = "urn:ietf:wg:oauth:2.0:oob";
        string scope = WebUtility.UrlEncode("openid offline_access https://graph.microsoft.com/user.read");
        string MicrosoftURL = "https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize?client_id=" + MicrosoftClientID + "&response_type=code&redirect_uri=" + MicrosoftCallbackURL + "&response_mode=query&scope=" + scope;

        Uri StartUri = new Uri(MicrosoftURL);
        Uri EndUri = new Uri(MicrosoftCallbackURL);

        WebAuthenticationResult WebAuthenticationResult = await WebAuthenticationBroker.AuthenticateAsync(
                                                WebAuthenticationOptions.None,
                                                StartUri,
                                                EndUri);
        if (WebAuthenticationResult.ResponseStatus == WebAuthenticationStatus.Success)
        {
            string code = WebAuthenticationResult.ResponseData.Replace("urn:ietf:wg:oauth:2.0:oob?code=", "");
            string strContent = "client_id=" + MicrosoftClientID + "&scope=" + scope + "&code=" + code + "&redirect_uri=" + MicrosoftCallbackURL + "&grant_type=authorization_code";

            HttpClient httpClient = new HttpClient();
            HttpContent httpContent = new StringContent(strContent);
            httpContent.Headers.ContentType = new MediaTypeHeaderValue("application/x-www-form-urlencoded");
            HttpResponseMessage httpResponseMessage = await httpClient.PostAsync("https://login.microsoftonline.com/consumers/oauth2/v2.0/token", httpContent);
            string stringResponse = await httpResponseMessage.Content.ReadAsStringAsync();
        }

我得到的只是登录页面的HTML

请帮忙吗?

2 个答案:

答案 0 :(得分:0)

此授权与普通Web应用程序相同。

如果您在调用此API时不想对用户进行身份验证,则可以删除 GetInfo 的属性 [授权] 。如果您还拥有控制器的 [授权] 属性,则可以添加 [AllowAnonymous] 属性,以指定授权期间AuthorizeAttribute会跳过此操作。

您可以参考有关身份验证和授权的here

答案 1 :(得分:0)

让我们从Web Api开始:

这是我从Api中检索朋友列表的示例方法。 请注意,在调用此方法之前,存在“路由前缀”属性 - 指示要检索的资源和“授权”属性以请求身份验证:

[RoutePrefix("api/Friends")]
public class FriendsController : ApiController
{
    [Authorize]
    [Route("GetConfirmedFriends")]
    public IHttpActionResult GetConfirmedFriends()
    {
        using (DbWrapper dbContext = new DbWrapper())
        {
            return Ok(dbContext.GetConfirmedFriends());
        }
    }
}

现在在UWP应用程序中,您将调用此方法,如下所示:

public async Task<ObservableCollection<Friend>> GetConfirmedFriends()
    {
       //access token eretrieved after MS authentication:
        if (_accessToken == null)
            throw new NullReferenceException("Access token cannot be empty. Please authenticate first");
        try
        {
            using (HttpClient client = new HttpClient())
            {
                ObservableCollection<Friend> friends = null;
                client.DefaultRequestHeaders.Add("Authorization", "Bearer " + _accessToken);
                var data = await client.GetAsync(string.Concat(https://{host}.azurewebsites.net/, "api/Friends/GetConfirmedFriends"));
                var jsonResponse = await data.Content.ReadAsStringAsync();
                if (jsonResponse != null)
                    friends = JsonConvert.DeserializeObject<ObservableCollection<Friend>>(jsonResponse);
                return friends;
            }
        }

        catch (WebException exception)
        {
            throw new WebException("An error has occurred while calling GetConfirmedFriends method: " + exception.Message);
        }
    }

请检查并告知我们。