---
title: Miniapp Login
---

## Miniapp Login

You can retrieve the app user's identifier through APIs to efficiently set up a miniapp user system.

### Login process

<Image
  src="/images/guide/login/login-en.png"
  style={{
    borderRadius: '10px',
    padding: 24,
    boxShadow: '0 0 5px rgba(0,0,0,0.3)',
  }}
/>

#### Description

1. Call `ty.login()` to get the temporary login credential code and send the code to your server.
2. Your server calls the Tuya cloud development API `/1.0/token` and passes in the code to get the `access_token` and `uid`. Then, you customize the login status based on the `access_token` and `uid` and send it to the frontend for further interaction.

> Note: Before developing a miniapp, make sure that the miniapp is already associated with your cloud project. For more information, see Server Development below.

### Server development

To call the Tuya cloud development API, you need to create a cloud project and associate it with your miniapp.

1.  Go to [Tuya Developer Platform](https://iot.tuya.com/) > Cloud > Development > Create Cloud Project, and create a cloud project as instructed.

          <Image

    src="/images/guide/login/create-cloud-en.png"
    style={{
        borderRadius: '10px',
        padding: 24,
        boxShadow: '0 0 5px rgba(0,0,0,0.3)',
    }}
    />

2.  After creating a project, open the project overview page and find the Client ID and Client Secret used for signing requests.

          <Image

    src="/images/guide/login/cloud-detail-en.png"
    style={{
        borderRadius: '10px',
        padding: 24,
        boxShadow: '0 0 5px rgba(0,0,0,0.3)',
    }}
    />

3.  Go to the Tuya MiniApp Developer Platform. Click `Development` and then `Add` to associate with your cloud project.

          <Image

    src="/images/guide/login/cloud-setting-en.png"
    style={{
        borderRadius: '10px',
        padding: 24,
        boxShadow: '0 0 5px rgba(0,0,0,0.3)',
    }}
    />

          <Image

    src="/images/guide/login/cloud-setting1-en.png"
    style={{
        borderRadius: '10px',
        padding: 24,
        boxShadow: '0 0 5px rgba(0,0,0,0.3)',
    }}
    />

#### Reference

- [Cloud Development](https://developer.tuya.com/en/docs/iot/introduction-to-tuya-iot-platform?id=Ka6vijvqb3uhn)
- [Sign Requests](https://developer.tuya.com/en/docs/iot/singnature?id=Ka43a5mtx1gsc)
- [ty.login](/en/miniapp/develop/miniapp/api/login/login)

### Example

#### Ray code

```js | pure
import {
  login,
  getUserInfo,
  request,
  setStorageSync,
  showModal,
} from '@ray-js/ray';

const { code } = await login({});

const { nickName, avatarUrl } = await new Promise((resolve, reject) =>
  getUserInfo({ success: resolve, fail: reject })
);

request({
  url: 'https://www.xxx.com/login',
  method: 'POST',
  header: {
    'Content-Type': 'application/json',
  },
  data: JSON.stringify({
    code,
    nickName,
    avatarUrl,
  }),
  success: ({ data }: any) => {
    setStorageSync({ key: 'session', data });
  },
  fail: () => {
    showModal({
      title: 'Tips',
      content: 'Login Failure',
      showCancel: false,
    });
  },
});
```
#### Miniapp Example

```js | pure
ty.login({
  success: ({ code }) => {
    ty.getUserInfo({
      success: ({ nickName, avatarUrl }) => {
        ty.request({
          url: 'https://www.xxx.com/login',
          method: 'POST',
          header: {
            'Content-Type': 'application/json',
          },
          data: JSON.stringify({
            code,
            nickName,
            avatarUrl,
          }),
          success: ({ data }: any) => {
            ty.setStorageSync({
              key: 'session',
              data,
            });
          },
          fail: (err) => {
            console.log('err', err);
            ty.showModal({
              title: 'Tips',
              content: 'Login Failure',
              showCancel: false,
            });
          },
        });
      },
      fail: (err) => {
        console.log('getUserInfo err', err);
      },
    });
  },
});
```

#### Server code in Node.js Koa

```js | pure
import Koa from 'koa';
import KoaRouter from 'koa-router';
import crypto from 'crypto';
import axios from 'axios';
import bodyParser from 'koa-bodyparser';

const app = new Koa();
const router = new KoaRouter();
const accessKey = 'Cloud Project Client ID';
const secretKey = 'Cloud Project Client Secret';

router.post('/login', async (ctx) => {
  const { code, nickName, avatarUrl } = ctx.request.body;

  const path = `/v1.0/token?code=${code}&grant_type=2`;
  const contentHash = crypto.createHash('sha256').update('').digest('hex');
  const t = +new Date();
  const nonce = '';
  const stringToSign = ['GET', contentHash, '', path].join('\n');
  const signStr = [accessKey, t, nonce, stringToSign].join('');
  const sign = crypto
    .createHmac('sha256', secretKey)
    .update(signStr, 'utf8')
    .digest('hex')
    .toUpperCase();

  const { data } = await axios({
    // Different countries/regions use their dedicated domain name address. Here is the URL for China Data Center:
    url: `https://openapi.tuyacn.com/v1.0/token?code=${code}&grant_type=2`,
    method: 'GET',
    headers: {
      t,
      sign,
      client_id: accessKey,
      sign_method: 'HMAC-SHA256',
      Dev_lang: 'Nodejs',
      'Signature-Headers': '',
    },
  });

  let responseData;
  if (data.success) {
    responseData = {
      success: true,
      result: {
        sessionId: '1234567890', // The server generates a unique ID to manage the MiniApp login status.
      },
    };
  } else {
    responseData = {
      success: false,
      errMsg: data.msg,
      errCode: data.code,
    };
  }
  ctx.body = responseData;
});

app.use(bodyParser()).use(router.allowedMethods()).use(router.routes());

app.listen(3000, async () => {
  console.log(`Server start on http://localhost:9000`);
});
```
