Как использовать конечные точки Next.JS Rest, защищенные с помощью Amplify, из приложения React Native

Фон:

Мой текущий стек — это сервер Next для использования в качестве портала администрирования и REST API для мобильного приложения, работающего с Expo — React Native. Следующий сервер в настоящее время размещен как [email protected]

Я защитил сервер Next и приложение React Native с помощью оболочки withAuthenticator от AWS Amplify. (Я также пробовал определенные пакеты аутентификации, такие как пакет аутентификации Next-Auth и Expo)

Проблема:

Однако я не могу понять, как добавить информацию об аутентификации (Access_token) в мои запросы REST из мобильного приложения -> Следующий сервер

Я безуспешно пытался добавить токены в качестве заголовков носителя в API, после чего был уверен, что все это должно быть настроено и отправлено через файлы cookie. НО я застрял в том, как правильно реализовать эти файлы cookie. Я надеялся, что конечные точки:[] config можно будет использовать для настройки моего собственного домена для публикации и обработки файлов cookie. Чтение запроса на сервере показало, что он не содержал информации об аутентификации при отправке с помощью этого метода.

Аналогичным образом, используя RTK Query (предпочтительно я добавляю к этому всю аутентификацию вместо настройки API Amplify). У меня нет правильной информации для отправки авторизованного запроса API.

Вот несколько фрагментов рабочей страницы Аутентификация для обоих приложений.

Конечная точка API /api/версия:

      import type { NextApiRequest, NextApiResponse } from 'next'
import { withSSRContext } from 'aws-amplify'

export default async function handler(
    req: NextApiRequest,
    res: NextApiResponse<Data | Error>,
) {
    const { Auth } = withSSRContext({req})

    try {
        const user = await Auth.currentAuthenticatedUser()
        return res.status(200).json({
            version: '1.0.0',
            user: user.username,
        })
    } catch (err) {
        console.log(err)
        return res.status(200).json({
            message: 'Unauthenticated',
        })
    }
}

Конфигурация мобильного приложения:

      import {
    useAuthenticator,
    withAuthenticator,
} from '@aws-amplify/ui-react-native'
import { Amplify, Auth } from 'aws-amplify'
import awsconfig from './aws-exports'

Amplify.configure({
    ...awsconfig,
    API: {
        endpoints: [
            {
                name: 'MyApi',
                endpoint: 'http://NextIP:NextPort/api/',
            },
        ],
    },
})

Auth.configure(awsconfig)

export default withAuthenticator(App)

Мобильный экран:

      import { API } from 'aws-amplify'

function getData() {
    const apiName = 'MyApi'
    const path = '/version'
    const myInit = {
        headers: {}, // OPTIONAL
    }

    return API.get(apiName, path, myInit)
}

export default function ModalScreen() {
    // Get token / Cookie for auth

    // const { data, isLoading, error } = useGetApiVersionQuery(null) // RTK Query
    getData() // Amplify
        .then(response => {
            console.log(response)
        })
        .catch(error => {
            console.log(error.response)
        })
    return ( <></>)}

1 ответ

Я нашел решение, однако не смог заставить промежуточное ПО Next-Auth срабатывать, когда токен был отправлен с использованием токена Bearer в заголовках. Это мой идеальный способ обработки маршрутов.

Я обернул вызов getToken({req}) так, чтобы, если нет веб-токена JWT, он попытался закодировать токен отдельно. aws-amplify/auth, в моем случае из react-native.

компоненты/утилиты/auth.utils.ts

      import { NextApiRequest } from 'next'
import { CognitoJwtVerifier } from 'aws-jwt-verify'
import { getToken } from 'next-auth/jwt'

// Verifier that expects valid token:
const verifier = CognitoJwtVerifier.create({
    userPoolId: process.env.COGNITO_USERPOOL_ID ?? '',
    tokenUse: 'id',
    clientId: process.env.COGNITO_CLIENT_ID ?? '',
    issuer: process.env.COGNITO_ISSUER ?? '',
})

export async function getMobileToken(req: NextApiRequest) {
    let token = null
    try {
        token = await getToken({ req })
    } catch (error) {
        console.log('Could not get JWT Web Token')
    }
    try {
        if (!token)
            token = await getToken({
                req,
                async decode({ token }) {
                    if (!token) return null
                    const decoded = await verifier.verify(token)
                    return decoded
                },
            })
    } catch (error) {
        return null
    }
    console.log('Mobile Token:', token)
    return token
}

Другие вопросы по тегам