一般的社交提供商不提供一个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. JSF 2 link, commandLink and outputLink example

    In JSF, <h:link />, <h:commandLink /> and <h:outputLink /> tags are used to render ...

  2. WinForm控件使用文章收藏整理完成

    对C# WinForm开发系列收集的控件使用方面进行整理, 加入了一些文章, 不断补充充实, 完善这方面. 基础 - 常用控件 C# WinForm开发系列 - CheckBox/Button/Lab ...

  3. CMSIS-DAP调试器

    http://www.keil.com/support/man/docs/dapdebug/dapdebug_introduction.htm CMSIS-DAP is the interface f ...

  4. Linux错误代码

    #ifndef _I386_ERRNO_H #define _I386_ERRNO_H #define EPERM 1 /* Operation not permitted */ #define EN ...

  5. Windows常用性能计数器总结

    基础监控: Processor:% Processor Time CPU当前利用率,百分比 Memory:Available MBytes 当前可用内存,兆字节(虚拟内存不需要监控,只有当物理内存不够 ...

  6. [MySQL复制异常]'Cannot execute statement: impossible to write to binary log since statement is in row format and BINLOG_FORMAT = STATEMENT.'

    MySQL复制错误]Last_Errno: 1666 Last_Error: Error executing row event: 'Cannot execute statement: imposs ...

  7. 使用 DLL 的优点

    动态链接具有下列优点: 节省内存和减少交换操作.很多进程可以同时使用一个 DLL,在内存中共享该 DLL 的一个副本.相反,对于每个用静态链接库生成的应用程序,Windows 必须在内存中加载库代码的 ...

  8. (转)用AGG实现高质量图形输出(四)

    AGG的字符输出 字符输出,对于AGG来说,这个功能可以处于显示流程的 不同位置.比如字体引擎可直接处于“Scanline Rasterizer”层向渲染器提供已处理完毕的扫描线,也可以处于“Vert ...

  9. C++ Code_ScrollBar

    主题 1.  ScrollBar的使用 2. 3. 4. 5.      属性 HScrollBar VScrollBar 直接拖拽1其中任意空间到对话框上面是,你一拖拽滚动条,它立即回到原始位置   ...

  10. 抛砖引玉:关于Android的ListView中CheckBox错乱

    首先:参考了这篇翻译的文章:http://www.cnblogs.com/xiaowenji/archive/2010/12/08/1900579.html 文章中关于说的Android中的Recyc ...