一般的社交提供商不提供一个Web Service进行身份验证(有很好的理由),而提供一个身份验证的界面,其中包含了某种协议如OpenID(连接)或使用OAuth2认证。这意味着客户端应用必须使用一个浏览器来展现这些UI部件---典型的登录页面和一些类型的许可界面。

这通常通过导航到一个众所周知的URL (网页API的模板使用OAuth2隐流程方法),并等待,直到在其他一些知名的URL会发生回调。在回调的访问令牌(加上一些元数据)通过散列片段连接。什么是之间发生的事情是总长达授权服务器,其与外部登录供应商的协调。客户端不需要知道该怎么做,这是很好的。

个人帐户帐户控制功能,查询已注册的中间件,并告诉和客户端的外部供应商提供哪些URL它必须使用来获得流量去的端点。这个信息可以被用来塑造客户端应用程序的用户界面:

private async Task GetExternalLoginsAsync()
{
var client = new HttpClient { BaseAddress = new Uri(_baseAddress) };
var response = await client.GetAsync(
“api/account/externalLogins?returnUrl=/&generateState=true”);
response.EnsureSuccessStatusCode(); _externalLogins = await response.Content.ReadAsAsync<
List<ExternalLoginViewModel>>();
}

外部登录模型如:

public class ExternalLoginViewModel
{
public string Name { get; set; }
public string Url { get; set; }
public string State { get; set; }
}

Url is the start URL (the callback URL is hardcoded to the base address in the template) and State is a random number that gets round tripped and should be checked on the callback (see the OAuth2 spec for details). The Url looks like this (sample):

/api/Account/ExternalLogin?
  provider=Google&
  response_type=token&
  client_id=self&
  redirect_uri=https://localhost/&
  state=as..aaa

The /api/account/externalLogin endpoint maps to the GetExternalLogin action on the account controller which has quite an interesting combination of attributes:

[OverrideAuthentication]
[HostAuthentication(DefaultAuthenticationTypes.ExternalCookie)]
[AllowAnonymous]
[Route("ExternalLogin", Name = "ExternalLogin")]

This basically means: don’t care about bearer tokens but allow anonymous access or an external cookie (see part 1).

In addition this endpoint also maps to the authorize endpoint of the OAuth2 authorization server middleware (check startup) which is kind of a black belt trick. First the middleware processes the request and then passes it on to whatever framework handles the URL – in this case Web API.

The exact course of events is quite involved. Let’s start with the moment when the web view hits the URL for the first time (check out the source code in parallel):

  1. Access /api/account/externalLogin?provider=Google…
    1. the user is not authenticated
    2. signal the middleware that is responsible for the requested external provider to do the protocol handshake (in this case Google)
  2. The user signs in at Google and does the consent
    1. Google calls back to the Web API using the /signin-google URL
  3. The Google middleware does its back channel communication and sets an external cookie containing some of the claims that came back from Google
    1. the middleware then redirects back to the /api/account/externalLogin endpoint
  4. This time the user is authenticated via the external cookie
    1. The account controller now checks if the login provider / user id combination is already registered in the local database
    2. this is not the case, so the account controller passes control back to the authorization server middleware instructing it to issue a token that contains the claims from Google (external bearer – the claims issuer is Google – again – check part one for the subtle meaning of that).
  5. The callback URL is invoked, and the client application retrieves the access token

At this point the client app has an access token, but it won’t get accepted by default since the claims are not issued by LOCAL AUTHORITY but Google instead. At this point you could open up endpoints by adding:

[HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]

One endpoint that is configured exactly like that is the /api/account/registerExternal. This endpoints accepts the token you get from the previous step and allows it to associate with a new local account (without a password):

private void RegisterExternal_Click(object sender, RoutedEventArgs e)
{
var client = new HttpClient { BaseAddress = new Uri(_baseAddress) };
client.SetBearerToken(_externalResponse.AccessToken); var data = new Dictionary<string, string>
{
{ “UserName”, “dominick” }
}; var response = client.PostAsync(
“api/account/registerExternal”,
new FormUrlEncodedContent(data)).Result;
response.EnsureSuccessStatusCode();
}

RegisterExternal uses the ASP.Identity API to create a new user account and associates that with the external provider and user id from the token.

Now the last step is to go back to /api/account/externalLogin to get a new token that now represents a local account (or technically speaking claims from LOCAL AUTHORITY). The flow is like this:

  1. Invoke externalLogin with the same URL as before
    1. the user is still authenticated using the same external cookie
    2. the login provider / user id pair is now registered
  2. The controller clears the external cookie
    1. and creates a new authentication ticket
    2. this ticket translates to a new token with an issuer of LOCAL AUTHORITY – aka local account
  3. The callback URL transmits the token back to the client

Mission accomplished – the client used an external login provider to authenticate the user and linked that login to an account in its backend. Quite a stunt.

Web Api 2 用户认证模板解析-----外部用户认证模式的更多相关文章

  1. Web Api2 用户认证模板解析---本地用户

    本文我们将把关注Visual Studio用户认证模板中的 本地用户名/密码帐号特性.他们将其分为了两部分:帐户控制器具备如创建帐号和修改密码等功能:另一部分是在OAuth2认证服务器中进行的认证.我 ...

  2. ASP.NET Web API 安全验证之摘要(Digest)认证

    在基本认证的方式中,主要的安全问题来自于用户信息的明文传输,而在摘要认证中,主要通过一些手段避免了此问题,大大增加了安全性. 1.客户端匿名的方式请求 (无认证) HTTP/ Unauthorized ...

  3. ASP.NET Web API与Owin OAuth:调用与用户相关的Web API

    在前一篇博文中,我们通过以 OAuth 的 Client Credential Grant 授权方式(只验证调用客户端,不验证登录用户)拿到的 Access Token ,成功调用了与用户无关的 We ...

  4. ASP.NET Web API与Owin OAuth:调用与用户相关的Web API(非第三方登录)

    授权完成添加属性 ClaimsIdentity oAuthIdentity = await CreateAsync(user/*userManager*/, OAuthDefaults.Authent ...

  5. Asp.net MVC使用FormsAuthentication,MVC和WEB API可以共享身份认证 (转载)

    在实际的项目应用中,很多时候都需要保证数据的安全和可靠,如何来保证数据的安全呢?做法有很多,最常见的就是进行身份验证.验证通过,根据验证过的身份给与对应访问权限.同在Web Api中如何实现身份认证呢 ...

  6. ASP.NET Web API安全认证

    http://www.cnblogs.com/codeon/p/6123863.html http://open.taobao.com/docs/doc.htm?spm=a219a.7629140.0 ...

  7. 控制台程序(C#)不弹出认证窗口连接到Dynamics CRM Online的Web API

    摘要: 本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复271或者20180602可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyon ...

  8. Web API 2 入门——使用ASP.NET Web API和Angular.js构建单页应用程序(SPA)(谷歌翻译)

    在这篇文章中 概观 演习 概要 由网络营 下载网络营训练包 在传统的Web应用程序中,客户机(浏览器)通过请求页面启动与服务器的通信.然后,服务器处理请求,并将页面的HTML发送给客户端.在与页面的后 ...

  9. 在一个空ASP.NET Web项目上创建一个ASP.NET Web API 2.0应用

    由于ASP.NET Web API具有与ASP.NET MVC类似的编程方式,再加上目前市面上专门介绍ASP.NET Web API 的书籍少之又少(我们看到的相关内容往往是某本介绍ASP.NET M ...

随机推荐

  1. TdxAlertWindowManager右下角HINT显示控件

    带爱像的右下角HINT显示,自动隐藏 function alterInfo: TdxAlertWindowManager;begin  if not Assigned(Falter) then  be ...

  2. Swift项目兼容Objective-C问题汇总

    Swift项目兼容Objective-C问题汇总 转载自 http://www.cocoachina.com/swift/20150608/12025.html 本文是投稿文章,作者:一叶(博客)欢迎 ...

  3. HDU 1312 Red and Black DFS(深度优先搜索) 和 BFS(广度优先搜索)

    Red and Black Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total ...

  4. css 精灵的用法

    (从已经死了一次又一次终于挂掉的百度空间人工抢救出来的,发表日期2014-02-12) 是指将多个图整合到一张图上,避免多次请求服务器下载. 主要使用CSS background-position 属 ...

  5. AspNet上传文件的几个控件

    本文转载:http://www.cnblogs.com/downmoon/archive/2009/02/05/1384931.html 1.AspnetUpload 地址:http://www.as ...

  6. intval()和(int)转换使用与区别

    <?php echo "<br/>数值强制转换:"; $string="2a"; $string1=intval($string); echo ...

  7. RDD的依赖关系

    RDD的依赖关系 Rdd之间的依赖关系通过rdd中的getDependencies来进行表示, 在提交job后,会通过在DAGShuduler.submitStage-->getMissingP ...

  8. MySQL中进行树状所有子节点的查询

    在Oracle 中我们知道有一个 Hierarchical Queries 通过CONNECT BY 我们可以方便的查了所有当前节点下的所有子节点.但很遗憾,在MySQL的目前版本中还没有对应的功能. ...

  9. hadoop分布式部署(2014-3-8)

    hadoop简介: (维基百科)Apache Hadoop是一款支持數據密集型分佈式應用并以Apache 2.0許可協議發佈的開源軟體框架.它支持在商品硬件構建的大型集群上運行的應用程序.Hadoop ...

  10. 制作Windows的ico图标

    也不知道这个方法是不是最好的,有时间再查看其它方法 首先设计出图标,png格式即可. 使用一款软件 IconWorkshop 下载了一个试用版,临时制作够用了 制作步骤如下: 1.打开png图片 2. ...