Next.js-KACAログイン実施
今回のプロジェクトは登録部分を担当します.
Kakaoログインと電子メールログインを実現するには、バックエンド開発者が作成したapiがすでにあるので、簡単にできるはずです...
途中で私の知っている方法でやらなかったので,新しい方法を探してやったので,少し苦労した.😂
その過程で学んだことを整理したい.
Kakaoログイン
Yaytomatoの声 araisのねじ
Kakaoログインと電子メールログインを実現するには、バックエンド開発者が作成したapiがすでにあるので、簡単にできるはずです...
途中で私の知っている方法でやらなかったので,新しい方法を探してやったので,少し苦労した.😂
その過程で学んだことを整理したい.
Kakaoログイン
まず、KACAログインを実施した内容を確認する前に、KACAログインの手順を確認します:
この絵(出ている:https://data-jj.tistory.com/53)に合っています.
フロントで話した部分は1번, 2번, 3번, 8번
で、reactを使用したプロジェクトで以前やったようにしようとしましたが、計画はこうです.
まず,kakaoのapiで承認コードを取得する.
第二に、apiを介して受信した承認コードをサーバに渡す.
第3に、apiは、戻り値をJWT
に渡し、復号してユーザ情報として使用し、登録情報を保持するためにlocalStorage
に格納する.
3つ目の過程で問題が発生しました👿
👊 問題の原因
nextjs
を用いてレンダリングを行うためには、サーバ側からデータを取得し、この場合はユーザのデータが必要となり、JWT
を復号してインポートする必要がある.ただし、サーバ側はlocalStorageにアクセスできないため、エラーが発生しました.
🤔 ソリューション
問題を解決するために、Googleを使用する場合、通常はJWT
をcookie
に格納して管理します.このプロセスでは、localStorageに格納されているセキュリティの問題も理解しました.もちろん、現在のプロジェクトでは、Access Token
とRefresh Token
は、いずれもkakao自身が管理・更新しているので関係ありませんが、今後はAccess Token
とRefresh Token
を直接管理できるので、勉強したほうがいいです.
ローカルストレージ
localStorageに保存すると、XSS攻撃でJWTを奪われる可能性があります!
https://academind.com/tutorials/localstorage-vs-cookies-xss
クッキーストレージ
クッキーの格納方式もXSS、CSRF攻撃から解放されないが、クッキーのSameSite, httpOnly, Secureなどの属性はある程度セキュリティ問題を解決している.さらに、JWT
が他のドメインで使用されず、apiサーバも同じドメインを使用する場合、Access Token
およびRefresh Token
は、cookie
に含めて管理することができる.この詳細については、投稿2投稿を参照してください.
クライアントコードにcookie
を設定するプロセスを非表示にし、ログイン情報をプレゼンテーションページに適用するために、nextjs
のapi-route機能が使用される.
👍 トラブルシューティング
まず,kakaoのapiで承認コードを取得する.
2番目に受信した承認コードは、/api/loginKakao
パスのapiを呼び出し、nextサーバに転送する.
第三に、nextサーバはapiを呼び出し、ライセンスコードをサーバに渡します.
4番目に返されるJWT
は、set-header
を介してcookie
に格納される.error
が受信されると、error
メッセージがクライアントに送信される.
クライアントコード
// 1.kakao에서 인증코드 받아오기
const login = () => {
window.Kakao.Auth.login({
throughTalk: false,
success: function (authObj) {
onSuccess(authObj);
},
fail: function (err) {
console.log('카카오에서 인증코드 받아오는 과정에서 오류발생', err);
alert('카카오에서 인증코드 받아오는 과정에서 오류발생');
},
});
};
const onSuccess = async (res) => {
// 2.인증코드를 받아오는데 성공하면 next서버로 인증코드를 보냄
await axios
.post('/api/loginKakao', {
token_type: res.token_type,
access_token: res.access_token,
expires_in: res.expires_in,
refresh_token: res.refresh_token,
refresh_token_expires_in: res.refresh_token_expires_in,
})
.catch((err) => {
console.log(err);
alert('서버에서 오류발생');
});
//로그인 성공 후 이전 홈으로 이동
router.push('/');
};
apiサーバコード
import axios from 'axios';
import { LOGIN_WITH_KAKAO } from '/gql/_mutation';
export default async function loginKakao(req, res) {
const {
body: {
token_type,
access_token,
expires_in,
refresh_token,
refresh_token_expires_in,
},
} = req;
//우리 서버로 토큰을 넘기는 과정
const { data } = await axios
.post(process.env.NEXT_PUBLIC_API_SERVER, {
query: LOGIN_WITH_KAKAO,
variables: {
access_token: access_token,
expires_in: expires_in,
refresh_token: refresh_token,
refresh_token_expires_in: refresh_token_expires_in,
token_type: token_type,
},
})
.catch((err) => {
res.status(500);
});
//쿠키에 저장
res.setHeader(
'Set-Cookie',
`celebstock=${data.data.loginKakao.jwt}; path=/; domain=.celebstock.kr; Max-Age=${refresh_token_expires_in}`,
);
res.status(200).send();
}
補足すべき点
cookie
にのみ保存され、cookie
に属性が正しく指定されていません.httpOnly
、samesite
のような属性は、後でさらに確認し、修正する必要がある場合があります.
References
// 1.kakao에서 인증코드 받아오기
const login = () => {
window.Kakao.Auth.login({
throughTalk: false,
success: function (authObj) {
onSuccess(authObj);
},
fail: function (err) {
console.log('카카오에서 인증코드 받아오는 과정에서 오류발생', err);
alert('카카오에서 인증코드 받아오는 과정에서 오류발생');
},
});
};
const onSuccess = async (res) => {
// 2.인증코드를 받아오는데 성공하면 next서버로 인증코드를 보냄
await axios
.post('/api/loginKakao', {
token_type: res.token_type,
access_token: res.access_token,
expires_in: res.expires_in,
refresh_token: res.refresh_token,
refresh_token_expires_in: res.refresh_token_expires_in,
})
.catch((err) => {
console.log(err);
alert('서버에서 오류발생');
});
//로그인 성공 후 이전 홈으로 이동
router.push('/');
};
import axios from 'axios';
import { LOGIN_WITH_KAKAO } from '/gql/_mutation';
export default async function loginKakao(req, res) {
const {
body: {
token_type,
access_token,
expires_in,
refresh_token,
refresh_token_expires_in,
},
} = req;
//우리 서버로 토큰을 넘기는 과정
const { data } = await axios
.post(process.env.NEXT_PUBLIC_API_SERVER, {
query: LOGIN_WITH_KAKAO,
variables: {
access_token: access_token,
expires_in: expires_in,
refresh_token: refresh_token,
refresh_token_expires_in: refresh_token_expires_in,
token_type: token_type,
},
})
.catch((err) => {
res.status(500);
});
//쿠키에 저장
res.setHeader(
'Set-Cookie',
`celebstock=${data.data.loginKakao.jwt}; path=/; domain=.celebstock.kr; Max-Age=${refresh_token_expires_in}`,
);
res.status(200).send();
}
Reference
この問題について(Next.js-KACAログイン実施), 我々は、より多くの情報をここで見つけました https://velog.io/@tunggary/NextJS-Jwt-로그인-구현テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol