如何使用环回 IP 检索身份验证令牌

How to use loopback IP to retrieve auth token

最近 Google 禁止嵌入式浏览器身份验证支持 Loopback IP 方法

我的网站有一个桌面客户端,它使用与网站相同的登录系统。基本上,我会在我的网站上弹出一个嵌入式浏览器视图,并在登录完成后获取 cookie。然后,我的站点的身份验证 cookie 用于桌面客户端的 API 访问。

既然 Google 禁止嵌入式浏览器,我需要一种新方法(如果我想保持 Google 外部登录)。

如果我没理解错的话,新流程应该是这样的
1.桌面端监听localhost::port
2. 桌面客户端启动 Url 到网站的登录页面并打开用户的默认浏览器
3. 用户使用自己喜欢的浏览器登录网站
4. Web 服务器检测到登录成功并以某种方式将带有身份验证令牌的重定向发送到 localhost::port
5. 桌面客户端从本地主机读取令牌

但是如果重定向 URL 是本地主机,我如何显示登录成功页面以指示用户关闭浏览器并 return 到桌面应用程序?我应该如何在服务器和桌面客户端上实现它?

找到了两种方法。一种是使用 TcpListener 并绑定到 Loopback IP。响应以流的形式返回,您需要进一步解析它以获得所需的数据,这是一个巨大的痛苦。

另一种方法是使用HttpListener

        using (HttpListener listener = new HttpListener())
        {
            listener.Prefixes.Add("http://localhost:{port}/"); //Only listen to this particular address
            listener.Start();

            //blocking call. Feel free to use async version
            HttpListenerContext context = listener.GetContext(); 
            HttpListenerRequest request = context.Request;

            HttpListenerResponse response = context.Response;

            //Here is the response url. The token should be inside url query param.
            Console.WriteLine(request.Url); 

            //redirects user back to your site and show a login success screen
            response.Redirect("{yourdomain}/loginsuccess");
            //Important! call close to send out the response
            response.Close();

            //Important! If listener is stopped before response is sent out then it will abort.
            Thread.Sleep(1000);
            listener.Stop();
        }

在服务器端,登录完成后只需将用户重定向到 http://localhost:{port}/?token=xxxx

asp.net 实施:

Startup.Auth.cs中添加静态字段

public static TicketDataFormat AccessTokenFormat;

ConfigureAuth

AccessTokenFormat = new TicketDataFormat(app.CreateDataProtector(typeof(OAuthAuthorizationServerMiddleware).Namespace, "Access_Token", "v1"));

app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

生成令牌

    TimeSpan tokenExpiration = TimeSpan.FromDays(1);

    ClaimsIdentity identity = new ClaimsIdentity(OAuthDefaults.AuthenticationType);
    identity.AddClaim(new Claim(ClaimTypes.Name, "a@a.com"));
    identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, "999"));

    AuthenticationProperties props = new AuthenticationProperties()
    {
        IssuedUtc = DateTime.UtcNow,
        ExpiresUtc = DateTime.UtcNow.Add(tokenExpiration),
    };

    AuthenticationTicket ticket = new AuthenticationTicket(identity, props);

    string accessToken = Startup.AccessTokenFormat.Protect(ticket);

使用此方法,用户甚至不会注意到我们已将 he/she 重定向到本地主机。浏览器的 URL 会一直显示您网站的域名。