在 Angular 中使用 ably.io JWT

Posted

技术标签:

【中文标题】在 Angular 中使用 ably.io JWT【英文标题】:Using ably.io JWT with Angular 【发布时间】:2020-09-30 00:49:16 【问题描述】:

我正在尝试使用 JWT 身份验证方式将 abil.io 与 Angular 和 Azure Functions 一起使用,因为它是安全的,但是我在配置它的角度方面时遇到了问题。该用例用于实时拍卖网站实时更新出价。没有针对此的特定角度教程,因此我试图将其拼凑起来。还有这段代码

          realtime.connection.once('connected', function () 
            console.log('Client connected to Ably using JWT')
            alert("Client successfully connected Ably using JWT auth")
          );

从不发出警报,所以我认为它工作不正常。我曾经让它在我不熟练使用 JWT 的地方工作,但在这样的组件中在客户端拥有 API 密钥

let api = "<api key>";
let options: Ably.Types.ClientOptions =  key: api ;
let client = new Ably.Realtime(options); /* inferred type Ably.Realtime */
let channel = client.channels.get(
  "auctions"
);

我可以订阅该频道并通过他们在ngOnInit()中的 ID 相应地更新拍卖

    channel.subscribe(message => 
      const auction = this.posts.find(action => 
        return action.id === message.data.auctionId;
      );

      if (auction) 
        auction.currentBid = message.data.lastBid;
      
    );

但我需要为 JWT 切换此逻辑,并以某种方式将该 JWT 令牌输入到不同的组件中。

Ably.io JWT tutorial reference

我将以下内容放入我的角度登录服务中

  login(email: string, password: string) 


    const authData: AuthDataLogin =  email: email, password: password ;
    return this.http
      .post<
        token: string;
        expiresIn: number;
        userId: string;
      >(environment.azure_function_url + "/POST-Login", authData)
      .pipe(takeUntil(this.destroy)).subscribe(response => 
        //JWT login token. Not Ably JWT Token
        const token = response.token; 
        this.token = token;




        if (token) 

          console.log('Fetching JWT token from auth server')

          var realtime = new Ably.Realtime(
            authUrl: "http://localhost:7071/api/AblyAuth"
          );
          realtime.connection.once('connected', function () 
            console.log('Client connected to Ably using JWT')
            alert("Client successfully connected Ably using JWT auth")
          );

...
  

已经配置了我的天蓝色功能,当我登录时,浏览器控制台输出

GET wss://realtime.ably.io/?access_token=<token was here>&format=json&heartbeats=true&v=1.1&lib=js-web-1.1.22

所以它会返回我的令牌,但是

    警报永远不会发生 我不确定如何获取返回给浏览器的 JWT 令牌。我在想我可以将它存储在 localStorage 中以在组件之间共享并在用户注销时清除 localStorage,但我需要能够订阅响应并将令牌分配给变量,但我没有在 javascript 教程中看到如何获取分配给 JWT 令牌响应的变量,因为它是使用此语法调用的。

感谢您对此提供的任何帮助!

       var realtime = new Ably.Realtime(
            authUrl: "http://localhost:7071/api/AblyAuth"
          );

我的天蓝色函数看起来像

const checkAuth = require('../middleware/check-auth');
var jwt = require("jsonwebtoken")
var appId = '<APP ID>'
var keyId = '<key ID>'
var keySecret = '<key secret>'
var ttlSeconds = 60

var jwtPayload =

  'x-ably-capability': JSON.stringify( '*': ['publish', 'subscribe'] )

var jwtOptions =

  expiresIn: ttlSeconds,
  keyid: `$appId.$keyId`

console.log("JwtPayload");
console.log(jwtPayload);
console.log("jwtOptions");
console.log(jwtOptions);

module.exports = function (context, req) 
  console.log("INSIDE ABLY AUTH")
  // checkAuth(context, req);
  console.log('Sucessfully connected to the server auth endpoint')
  jwt.sign(jwtPayload, keySecret, jwtOptions, function (err, tokenId) 


    if (err) 
      console.log("ERR")
      console.log(err)
      console.trace()
      return
    
    context.res.header('Cache-Control', 'private, no-cache, no-store, must-revalidate')
    context.res.setHeader('Content-Type', 'application/json')
    console.log('Sending signed JWT token back to client')
    console.log(tokenId)

    context.res = 

      status: 200,

      body: JSON.stringify(tokenId),

      headers: 
        "Access-Control-Allow-Credentials": "true",
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Methods": "GET, OPTIONS",
        "Access-Control-Allow-Headers": "Content-Type, Set-Cookie",
        "Access-Control-Max-Age": "86400",
        "Vary": "Accept-Encoding, Origin",
        "Content-Type": "application/json"
      

    ;

    context.done();
  )

【问题讨论】:

【参考方案1】:

如果您想在将 JWT 传递给 Ably 之前拦截它(以便验证内容,并将 JWT 用于其他组件),我建议您使用 authCallback 而不是 authUrl .在将 JWT 传递回 Ably 构造函数之前,您可以使用函数而不是直接 URL,在其中您可以调用端点,并对响应执行任何您喜欢的操作。我已经提出JavaScript example 使用 authCallback 进行普通令牌身份验证,但同样的原则也适用。

至于为什么您没有看到警报,看起来您发送的 JWT 与 Ably 的预期不符,因此您没有成功连接到 Ably。例如,您指定的是“expiresIn”而不是“exp”。对于一个被认为是有效的令牌,它期望特定结构中的某些元素,请参阅documentation。对于这种情况,我建议您不确定使用详细日志记录会破坏什么,您可以将其 enable in the connection constructor 设为 "log": 4

【讨论】:

以上是关于在 Angular 中使用 ably.io JWT的主要内容,如果未能解决你的问题,请参考以下文章

使用 Ably.io 创建连接时出现未知错误

连接使用Ably.io创建连接时出现Unknown错误

需要帮助在浏览器中将 MQTT 与 Ably 结合使用

在 Angular / Golang 项目中使用 JWT

如何检查 JWT 令牌是不是在 Angular 8 中过期

在 Angular 6 中解码 firebase/php-jwt