Video address: https://www.bilibili.com/video/BV12d4y1R7bR/


Initialize the project

Remix official website: https://remix.run/

Create command:

 npx create-remix@latest

The current project source code is located at: https://github.com/willin/beta.willin.wang

configure

  • eslint
  • prettier
  • editorconfig

Optional:

  • lint-staged
  • husky

Install dependencies

  • tailwindcss
  • daisyui
  • @tailwindcss/typography
  • postcss
  • pm2

Create Authing user pool and application

Create login and logout interfaces

login interface

 import { redirect } from '@remix-run/node';

export const loader = async () => {
  return redirect(
    `${process.env.AUTHING_SSO_URL}/login?app_id=${process.env.AUTHING_APP_ID}`
  );
};

logout interface

 import { redirect } from '@remix-run/node';

export const loader = async () => {
  return redirect(
    `${process.env.AUTHING_SSO_URL}/logout?redirectUri=${encodeURIComponent(
      process.env.HOMEPAGE || 'https://willin.wang'
    )}`
  );
};

login callback callback

 import { json, redirect } from '@remix-run/node';

export type OidcResponse = {
  error?: string;
  error_description?: string;

  access_token: string;
  expires_in: number;
  id_token: string;
  scope: string;
  token_type: string;
};

export const loader = async ({ request }) => {
  const url = new URL(request.url);
  const code = url.searchParams.get('code');
  if (code === null) {
    return redirect('/login');
  }

  const body = {
    client_id: process.env.AUTHING_APP_ID,
    client_secret: process.env.AUTHING_APP_SECRET,
    grant_type: 'authorization_code',
    code
  };

  const formBody = [];
  // eslint-disable-next-line
  for (const property in body) {
    const encodedKey = encodeURIComponent(property);
    // eslint-disable-next-line @typescript-eslint/ban-ts-comment
    // @ts-ignore
    // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
    const encodedValue = encodeURIComponent(body[property]);
    formBody.push(`${encodedKey}=${encodedValue}`);
  }
  const res = await fetch(`${process.env.AUTHING_APP_DOMAIN}/oidc/token`, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8'
    },
    body: formBody.join('&')
  });

  const oidcToken = (await res.json()) as OidcResponse;
  if (oidcToken.error) {
    console.error(oidcToken);
    return redirect('/login');
  }
  // 以上获取 oidc token 为核心部分
  
  // 下面根据业务需要去操作其他
  const resInfo = await fetch(
    `${process.env.AUTHING_APP_DOMAIN}/oidc/me?access_token=${oidcToken.access_token}`
  );
  // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
  const user = await resInfo.json();
  return json(user);
};

willin
213 声望12 粉丝

欢迎在各平台 Follow 我。