@555platform/author.ts 中文文档教程

发布于 3年前 浏览 18 更新于 3年前

Build

Author.ts

用于 OAuth 2.0 的同构 Typescript 工具包,

Install

来自 npm

npm install @555platform/Author.ts

Initialize - client

import { WebAuth } from '@555platform/Author.ts';

const webAuth = new WebAuth({
      domain: config.domain,
      clientID: config.clientID,
      responseType: 'code',
      redirectURI: config.redirectURI,
      scope: 'everything',
      authServer: config.authServer
    });

的 555 平台 以上是客户端 SDK 的典型初始化示例。 authServer 字段是可选的,默认为 555 平台生产服务器。

可用的响应类型有 codetokenid_tokenid_token token

Initialize - server

服务器端的示例初始化。 请注意,目前 SDK 辅助函数仅支持 express.js。

serverAuth = ServerAuth({
  domain: config.domain,
  clientID: config.clientID,
  clientSecret: config.clientSecret,
  redirectURI: config.redirectURI,
  authServer: config.authServer
});

Using response type code

使用响应类型代码时,您需要从客户端启动登录,这将带您进入 555 平台登录屏幕。 登录成功后,555 平台将重定向到应在应用服务器上实现的 URI。 为了实现这个流程,我们需要客户端和服务器端的代码。 让我们先从客户端代码开始。

const webAuth = new WebAuth({
      domain: config.domain,
      clientID: config.clientID,
      responseType: 'code',
      redirectURI: config.redirectURI,
      scope: 'everything',
      authServer: config.authServer
    });
    webAuth.login({ state: 'xyz' });

上面的代码将初始化 SDK 的客户端并使用响应类型代码启动登录流程。

现在在服务器端,我们需要使用 express.js 创建基本设置。 在 index.js 文件中:

const express = require('express');
const bodyParser = require('body-parser');
const cookieSession = require('cookie-session');
const cors = require('cors');

const app = express();
app.use(cors());
app.use(bodyParser.json());
app.use(
  cookieSession({
    maxAge: 30 * 24 * 60 * 60 * 1000,
    keys: ['victor is a cool cat']
  })
);

require('./routes/authRoutes')(app);

const PORT = process.env.PORT || 3033;
app.listen(PORT);

由于我们将使用 cookie 来存储 555 平台访问令牌,因此我们还包含了 cookie-session 模块。

接下来我们需要创建处理从登录页面重定向的路由。 在文件 routes/authRoutes.js 中添加以下代码:

const { ServerAuth } = require('@555platform/Author.ts');
const config = require('./config');

serverAuth = ServerAuth({
  domain: config.domain,
  clientID: config.clientID,
  clientSecret: config.clientSecret,
  redirectURI: config.redirectURI,
  authServer: config.authServer
});

serverAuth.serializeUser(payload => {
  return payload.access_token;
});

serverAuth.deserializeUser(payload => {
  return payload;
});

module.exports = app => {
  app.use(serverAuth.session);

  app.get(
    '/auth/555/callback',
    serverAuth.authenticate({
      successRedirect: config.loginSuccess,
      failureRedirect: config.loginFailure,
      state: 'xyz',
      nonce: '123'
    })
  );
}

我们做的第一件事是使用客户端 ID/密码、重定向 URI、域和可选的身份验证服务器 URL 初始化服务器端 SDK。

两次调用 serializeUserdeserializeUser 用于从 req.userreq.session.user。

我们还提供将用户对象附加到请求的 session 中间件。

最后,我们处理从 555 平台接收到 code 的 /auth/555/callback URI。 辅助函数 authenticate 负责访问令牌的整个代码交换,它将重定向到上面指定的成功或失败 URL。

还可以控制 authenticate 完成访问令牌的代码交换后发生的情况。 如果您不想自动重定向,请使用以下示例代码来引入您自己的逻辑:

app.get(
    '/auth/555/callback',
    serverAuth.authenticate({
      state: 'xyz',
      nonce: '123'
    }), (req, res) => {
    console.log('AUTH CHECK: ', req.auth)
    if (req.auth) {
      res.send({message: 'authed'})
      return
    }

    res.status(401).send({message: 'unauthorized'})
  }
);

注意:为了在 req.auth 中接收授权数据,请不要将函数传递给 serializeUser反序列化用户。 如果您这样做,req.auth 将不包含任何数据,而是 req.user 将包含您选择的反序列化信息。

Using response type implicit

对于隐式流程,您启动调用以从客户端登录并直接接收带有访问令牌和/或 ID 令牌的重定向 URL,而无需交换代码。 如果您想直接在客户端中处理身份验证,这将很有用。

使用以下示例代码使用隐式流程调用 SDK 启动登录:

import { WebAuth } from '@555platform/Author.ts';

.
.
.

const webAuth = new WebAuth({
      domain: config.domain,
      clientID: config.clientID,
      responseType: 'id_token token',
      redirectURI: config.implicitRedirectURI,
      scope: 'openid email',
      authServer: config.authServer
    });
    webAuth.login({ state: 'xyz' });

在这种情况下,登录完成后 555 平台将重定向到 redirectURI 中指定的 URL,示例值如下:

/implicit#access_token=<access_token>&expires_in=216000&id_token=<id_token>&scope=openid+email&state=xyz&token_type=Bearer

Identity APIs

身份 API 允许搜索用户或单个用户并更新用户信息.

Query for users

您可以对符合特定条件的用户执行查询,例如,user_namerob 开头。 可以通过提供 skiplimit 参数对搜索进行分页。 下面是一个例子:

const identity = new Identity();
identity
  .findUsers(
    '<server token>',
    { user_name: 'regex(.*rob.*) options(i)' }
  )
  .then((data: any) => console.log("Found users:", data))
  .catch((error: Error) => console.log("Error finding users", error));

Find single user by userId:

const identity = new Identity();
identity
  .findUser(
    "<server token>",
    "10c8f37c-057a-11ea-a90f-784f4371df5c"
  )
  .then((data: any) => console.log("Found user:", data))
  .catch((error: Error) => console.log("Error finding user", error));

Update user information

下面是一个更新 user_name 的例子:

const identity = new Identity();
identity
  .updateUser(
    "<server token>",
    "10c8f37c-057a-11ea-a90f-784f4371df5c",
    {
      user_name: "Rob Tester"
    }
  )
  .then((data: any) => console.log("Updated user:", data))
  .catch((error: Error) => console.log("Error updating user", error));

Subdomains

子域是域的子域。 它们可用于将多个域分组为单个应用程序所拥有的域,但每个域代表不同的身份集。 例如,这对于在 Slack 中实现诸如工作空间之类的概念很有用。

Create Subdomain

const serverAuth = new ServerAuth({
      domain: 'test.domain.com',
      clientID: 'blahblahblah',
      clientSecret: 'blahblahblah123',
      redirectURI: '/auth/iris/callback',
      authServer: 'http://localhost',
      userinfoRoot: '/oauth2'
    });

serverAuth
      .createSubdomain('<application name>', '<application friendly name>')
      .then(data => {
        console.log(data)
      })
      .catch(error => {
        console.log(error);
      });

Find Subdomains

findSubdomains 函数将返回匹配 friendlyName(第一个参数)或域名(第二个参数)的域列表。 每个参数都被视为 *value* 的正则表达式,因此它可以匹配多个条目。

例如,

const serverAuth = new ServerAuth({
      domain: 'test.domain.com',
      clientID: 'blahblahblah',
      clientSecret: 'blahblahblah123',
      redirectURI: '/auth/iris/callback',
      authServer: 'http://localhost',
      userinfoRoot: '/oauth2'
    });

    serverAuth
      .findSubdomains('bl', '')
      .then(data => {
        console.log('Found subdomaines', data)
      })
      .catch(error => {
        console.log(error);
      });

Login with Subdomain

要使用子域登录,请调用 buildSubdomainLoginURL 以检索要重定向到的 URL。 此 URL 将调用指定子域的作者登录。

serverAuth
      .buildSubdomainLoginURL('<subdomain friendly name>', '<state>', '<nonce>', '<scopes or everything>')
      .then(loginURL => {
        console.log(loginURL)
      })
      .catch(error => {
        console.log(error);
      });

Getting public key for the token's domain

Author SDK 提供便捷的 API 来自动查找指定令牌的公钥。 这在验证可以从多个域接收 JWT 的服务器上的 JWT 签名时非常有用。

例子,

import { getPublicKeysForToken } from '@555platform/author.ts';

const jwtPublicKey = await getPublicKeysForToken(
    accessToken,
    config.authServerUrl,
    15, // cache age in seconds, default 30s
  );

Build

Author.ts

Isomorphic Typescript toolkit for OAuth 2.0 with 555 Platform

Install

From npm

npm install @555platform/Author.ts

Initialize - client

import { WebAuth } from '@555platform/Author.ts';

const webAuth = new WebAuth({
      domain: config.domain,
      clientID: config.clientID,
      responseType: 'code',
      redirectURI: config.redirectURI,
      scope: 'everything',
      authServer: config.authServer
    });

The above is example of typical initialization of client side SDK. authServer field is optional and it will default to 555 Platform production server.

Available response types are code, token, id_token, and id_token token.

Initialize - server

Sample initialization on server side. Note, currently SDK helper functions support only express.js.

serverAuth = ServerAuth({
  domain: config.domain,
  clientID: config.clientID,
  clientSecret: config.clientSecret,
  redirectURI: config.redirectURI,
  authServer: config.authServer
});

Using response type code

When using response type code you will need to initiate login from the client side that will take you to 555 Platform login screen. After successful login 555 Platform will redirect to URI that should be implemented on application server. In order to implement this flow we will need code on both client and server. Let's start with the client code first.

const webAuth = new WebAuth({
      domain: config.domain,
      clientID: config.clientID,
      responseType: 'code',
      redirectURI: config.redirectURI,
      scope: 'everything',
      authServer: config.authServer
    });
    webAuth.login({ state: 'xyz' });

Above code will initialize client side of SDK and initiate login flow with response type code.

Now on the server side we will need to create basic set up with express.js. In the index.js file:

const express = require('express');
const bodyParser = require('body-parser');
const cookieSession = require('cookie-session');
const cors = require('cors');

const app = express();
app.use(cors());
app.use(bodyParser.json());
app.use(
  cookieSession({
    maxAge: 30 * 24 * 60 * 60 * 1000,
    keys: ['victor is a cool cat']
  })
);

require('./routes/authRoutes')(app);

const PORT = process.env.PORT || 3033;
app.listen(PORT);

Since we will be using cookie to store 555 Platform access token we also included cookie-session module.

Next we need to create route that will handle redirect from login page. In file routes/authRoutes.js add the following code:

const { ServerAuth } = require('@555platform/Author.ts');
const config = require('./config');

serverAuth = ServerAuth({
  domain: config.domain,
  clientID: config.clientID,
  clientSecret: config.clientSecret,
  redirectURI: config.redirectURI,
  authServer: config.authServer
});

serverAuth.serializeUser(payload => {
  return payload.access_token;
});

serverAuth.deserializeUser(payload => {
  return payload;
});

module.exports = app => {
  app.use(serverAuth.session);

  app.get(
    '/auth/555/callback',
    serverAuth.authenticate({
      successRedirect: config.loginSuccess,
      failureRedirect: config.loginFailure,
      state: 'xyz',
      nonce: '123'
    })
  );
}

The first thing we did is to initialize server side SDK with client ID/secret, redirect URI, domain and optional auth server URL.

Two calls serializeUser and deserializeUser are used to put/retrieve access token from the req.user and req.session.user.

We are also providing session middleware that attaches user object to the request.

Finally, we handle /auth/555/callback URI that received code from 555 Platform. Helper function authenticate takes care of entire exchange of code for access token and it will redirect to either success or failure URLs as specified above.

It is also possible to control what happens after authenticate completes code exchange for access token. If you rather not automatically redirect use the following sample code instead to introduce your own logic:

app.get(
    '/auth/555/callback',
    serverAuth.authenticate({
      state: 'xyz',
      nonce: '123'
    }), (req, res) => {
    console.log('AUTH CHECK: ', req.auth)
    if (req.auth) {
      res.send({message: 'authed'})
      return
    }

    res.status(401).send({message: 'unauthorized'})
  }
);

Note: In order to receive authorization data in req.auth do not pass functions to serializeUser and deserializeUser. If you do req.auth will not contain any data but rather req.user will contain deserialized information you selected.

Using response type implicit

For implicit flow you initiate call to login from the client and receive redirected URL with access token and/or id token directly without the need to exchange the code. This is useful if you want to handle authentication directly in the client.

To initiate login with implicit flow call SDK with the following sample code:

import { WebAuth } from '@555platform/Author.ts';

.
.
.

const webAuth = new WebAuth({
      domain: config.domain,
      clientID: config.clientID,
      responseType: 'id_token token',
      redirectURI: config.implicitRedirectURI,
      scope: 'openid email',
      authServer: config.authServer
    });
    webAuth.login({ state: 'xyz' });

In this case, after login is completed 555 Platform will redirect to URL specified in redirectURI with the following sample values:

/implicit#access_token=<access_token>&expires_in=216000&id_token=<id_token>&scope=openid+email&state=xyz&token_type=Bearer

Identity APIs

Identity APIs allow seearching for users or single user and updating user information.

Query for users

You can perform a query for users that match certain criteria, for example, user_name starts with rob. Search can be paginated by providing skip and limit parameters. Here is an example:

const identity = new Identity();
identity
  .findUsers(
    '<server token>',
    { user_name: 'regex(.*rob.*) options(i)' }
  )
  .then((data: any) => console.log("Found users:", data))
  .catch((error: Error) => console.log("Error finding users", error));

Find single user by userId:

const identity = new Identity();
identity
  .findUser(
    "<server token>",
    "10c8f37c-057a-11ea-a90f-784f4371df5c"
  )
  .then((data: any) => console.log("Found user:", data))
  .catch((error: Error) => console.log("Error finding user", error));

Update user information

Here is an example to update user_name:

const identity = new Identity();
identity
  .updateUser(
    "<server token>",
    "10c8f37c-057a-11ea-a90f-784f4371df5c",
    {
      user_name: "Rob Tester"
    }
  )
  .then((data: any) => console.log("Updated user:", data))
  .catch((error: Error) => console.log("Error updating user", error));

Subdomains

Subdomains are child domains of the domain. They are useful for grouping multiple domains as owned by single application but each domain represents different set of identities. This is useful for implementing concepts like workspaces in Slack for example.

Create Subdomain

const serverAuth = new ServerAuth({
      domain: 'test.domain.com',
      clientID: 'blahblahblah',
      clientSecret: 'blahblahblah123',
      redirectURI: '/auth/iris/callback',
      authServer: 'http://localhost',
      userinfoRoot: '/oauth2'
    });

serverAuth
      .createSubdomain('<application name>', '<application friendly name>')
      .then(data => {
        console.log(data)
      })
      .catch(error => {
        console.log(error);
      });

Find Subdomains

findSubdomains function will return list of domains that match either friendlyName (first parameter) or domain name (second parameter). Each parameter is treated as regex of *value* so it can match multiple entries.

For example,

const serverAuth = new ServerAuth({
      domain: 'test.domain.com',
      clientID: 'blahblahblah',
      clientSecret: 'blahblahblah123',
      redirectURI: '/auth/iris/callback',
      authServer: 'http://localhost',
      userinfoRoot: '/oauth2'
    });

    serverAuth
      .findSubdomains('bl', '')
      .then(data => {
        console.log('Found subdomaines', data)
      })
      .catch(error => {
        console.log(error);
      });

Login with Subdomain

To login with subdomain call buildSubdomainLoginURL to retrieve URL to redirect to. This URL will call Author login for specified subdomain.

serverAuth
      .buildSubdomainLoginURL('<subdomain friendly name>', '<state>', '<nonce>', '<scopes or everything>')
      .then(loginURL => {
        console.log(loginURL)
      })
      .catch(error => {
        console.log(error);
      });

Getting public key for the token's domain

Author SDK provides convenience API to automatically look up public key for the specified token. This is useful when validating signature of the JWT on the server that can receive JWTs from multiple domains.

Example,

import { getPublicKeysForToken } from '@555platform/author.ts';

const jwtPublicKey = await getPublicKeysForToken(
    accessToken,
    config.authServerUrl,
    15, // cache age in seconds, default 30s
  );
    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文