Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .node-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
24.12.0
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,10 @@

mainブランチの最新のコードで動作している<a href="https://main.d3s7y579k91bnt.amplifyapp.com/" target="_blank" rel="noopener noreferrer">デモ</a>を公開しています。

## 推奨動作環境
## 確認済動作環境

- Node.js: v18.16.0
- yarn: 1.22.19
- Node.js: v24.12.0
- yarn: 1.22.22
- 推奨ブラウザ: Chrome

## セットアップと実行
Expand Down
2 changes: 1 addition & 1 deletion components/UserIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { useCallback, useState } from 'react';
import { useRouter } from 'next/router';
import { signOut } from 'next-auth/client';
import { signOut } from 'next-auth/react';
import styled from 'styled-components';

type IconProps = {
Expand Down
10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"name": "sippo-vroidsdk-test2",
"name": "vroid-hub-api-example",
"version": "0.1.0",
"private": true,
"scripts": {
Expand All @@ -22,14 +22,18 @@
"@types/three": "^0.153.0",
"eslint": "^8.42.0",
"eslint-config-next": "13.4.4",
"jsonwebtoken": "^9.0.2",
"jwa": "^1.4.2",
"jws": "^3.2.2",
"next": "13.4.4",
"next-auth": "3",
"next-auth": "4.24.13",
"react": "18.2.0",
"react-dom": "18.2.0",
"react-use": "^17.4.0",
"styled-components": "^6.0.5",
"three": "^0.154.0",
"typescript": "^5.1.6"
"typescript": "^5.1.6",
"yarn": "^1.22.22"
},
"lint-staged": {
"*.{ts,tsx}": [
Expand Down
6 changes: 3 additions & 3 deletions pages/_app.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Provider } from 'next-auth/client';
import { SessionProvider } from 'next-auth/react';
import { ThemeProvider, createGlobalStyle } from 'styled-components';
import { light } from '@charcoal-ui/theme';
import { CharcoalProvider, OverlayProvider, SSRProvider } from '@charcoal-ui/react';
Expand All @@ -14,7 +14,7 @@ export default function App({ Component, pageProps }) {
<meta property="og:title" content="VRoid Hub API Example" />
<meta property="og:description" content="Simple example of VRoid Hub API" />
</Head>
<Provider session={pageProps.session}>
<SessionProvider session={pageProps.session}>
<SSRProvider>
<CharcoalProvider themeMap={{ ':root': light }}>
<OverlayProvider>
Expand All @@ -25,7 +25,7 @@ export default function App({ Component, pageProps }) {
</OverlayProvider>
</CharcoalProvider>
</SSRProvider>
</Provider>
</SessionProvider>
</>
);
}
Expand Down
80 changes: 51 additions & 29 deletions pages/api/auth/[...nextauth].ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,56 @@
import NextAuth, { Account, Profile, User } from 'next-auth';
import NextAuth from 'next-auth';

export default NextAuth({
providers: [
{
// The name to display on the sign in form (e.g. 'Sign in with...')
id: 'vroid',
name: 'VRoidHub',
type: 'oauth',
version: '2.0',
scope: 'default',
protection: ['state', 'pkce'],
params: { grant_type: 'authorization_code' },
accessTokenUrl: `${process.env.NEXT_PUBLIC_VROID_HUB_URL}/oauth/token`,
requestTokenUrl: `${process.env.NEXT_PUBLIC_VROID_HUB_URL}/oauth/token`,
authorizationUrl: `${process.env.NEXT_PUBLIC_VROID_HUB_URL}/authorize/confirm?response_type=code`,
profileUrl: `${process.env.NEXT_PUBLIC_VROID_HUB_URL}/api/account`,
headers: {
'X-Api-Version': 11,
type: 'oauth',
authorization: {
url: `${process.env.NEXT_PUBLIC_VROID_HUB_URL}/authorize/confirm?response_type=code`,
params: { scope: 'default' }
},
token: {
// v4でheadersを付与する場合独自拡張が必要になった https://next-auth.js.org/configuration/providers/oauth#token-option
url: `${process.env.NEXT_PUBLIC_VROID_HUB_URL}/oauth/token`,
params: { grant_type: 'authorization_code' },
async request({ params, client, checks }) {
const response = await fetch(
`${process.env.NEXT_PUBLIC_VROID_HUB_URL}/oauth/token`, {
headers: {
'X-Api-Version': '11' // VRoidHubAPI独自
},
method: 'POST',
body: new URLSearchParams({
...params,
client_id: client.client_id as string,
client_secret: client.client_secret as string,
grant_type: 'authorization_code',
code_verifier: checks.code_verifier as string,
redirect_uri: client.redirect_uris[0],
})
},
)

return { tokens: await response.json() };
}
},
userinfo: {
url: `${process.env.NEXT_PUBLIC_VROID_HUB_URL}/api/account`,
async request({ tokens }) {
const response = await fetch(`${process.env.NEXT_PUBLIC_VROID_HUB_URL}/api/account`, {
headers: {
'Authorization': `${tokens.token_type} ${tokens.access_token}`,
'X-Api-Version': '11', // VRoidHubAPI独自
}
});

return await response.json();
},
},
async profile(profile: any, tokens) {
// You can use the tokens, in case you want to fetch more profile information
// For example several OAuth providers do not return email by default.
// Depending on your provider, will have tokens like `access_token`, `id_token` and or `refresh_token`
checks: ['pkce', 'state'],
async profile(profile: any) {
return {
id: profile.data.user_detail.user.id,
name: profile.data.user_detail.user.name,
Expand All @@ -32,25 +61,18 @@ export default NextAuth({
clientSecret: process.env.CLIENT_SECRET,
},
],
secret: process.env.NEXT_PUBLIC_NEXTAUTH_SECRET,
callbacks: {
async jwt(token, user, account, profile, isNewUser) {
if (account?.accessToken) {
token.accessToken = account.access_token;
}
if (profile) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: JWTのtoken.idへの代入が消されていますが、これは不要になったのでしょうか?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

console.logで値を見ていたのですが、元からprofileにidは入っていなさそうだったので消しました。おそらく最初に実装していた際に、NextAuthのサンプルコードなどを参考にしていたのではないでしょうか?

ちなみにprofileに入りうるのは { data : CurrentUserSerializer, ... } のようなデータです

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

承知しました。確認ありがとうございます

token.id = profile.id;
async jwt({ token, account }) {
if (account?.access_token) {
token.accessToken = account?.access_token;
}

return token;
},

async session(session, token) {
async session({ session, token }) {
session.accessToken = token.accessToken;
return session;
},

async signIn(user: User, account: Account, profile: Profile) {
return true;
},
},
}
});
4 changes: 2 additions & 2 deletions pages/api/vroid/models/account.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getSession } from 'next-auth/client';
import { getSession } from 'next-auth/react';
import type { CharacterModelCollectionResponse, CharacterModelSerializer } from '@/types/Response';
import { NextApiRequest, NextApiResponse } from 'next';
import { vroidHubApi } from '@/lib/vroid-hub-api';
Expand Down Expand Up @@ -36,4 +36,4 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse)
resJson.data = apiResJson.data;

return res.status(200).json(resJson);
}
}
4 changes: 2 additions & 2 deletions pages/api/vroid/models/hearts.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getSession } from 'next-auth/client';
import type { CharacterModelCollectionResponse, CharacterModelSerializer } from '@/types/Response';
import { getSession } from 'next-auth/react';
import { CharacterModelCollectionResponse, CharacterModelSerializer } from '../../../../types/Response';
import { NextApiRequest, NextApiResponse } from 'next';
import { vroidHubApi } from '@/lib/vroid-hub-api';

Expand Down
2 changes: 1 addition & 1 deletion pages/api/vroid/models/staff_picks.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { getSession } from 'next-auth/client';
import type { CharacterModelSerializer, HeartCollectionResponse } from '@/types/Response';
import { getSession } from 'next-auth/react';
import { NextApiRequest, NextApiResponse } from 'next';
import { vroidHubApi } from '@/lib/vroid-hub-api';

Expand Down
2 changes: 1 addition & 1 deletion pages/api/vroid/vrm.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { getSession } from 'next-auth/client';
import { getSession } from 'next-auth/react';
import type { NextApiRequest, NextApiResponse } from 'next';
import { fetchVRMModel } from '../../../lib/vroid-hub-api';

Expand Down
5 changes: 3 additions & 2 deletions pages/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { signIn, useSession } from 'next-auth/client';
import { signIn, useSession } from 'next-auth/react';

import React, { useCallback, useState } from 'react';
import { useAsync } from 'react-use';
import { useRouter } from 'next/router';
Expand All @@ -15,7 +16,7 @@ type ModelsListState = {
};

export default function Index() {
const [session] = useSession();
const { data: session } = useSession()
const router = useRouter();

// ユーザーが保持しているモデルの一覧
Expand Down
27 changes: 26 additions & 1 deletion types/next-auth.d.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,28 @@
import NextAuth from 'next-auth';
import { DefaultSession } from "next-auth";
import { JWT } from "next-auth/jwt";

declare module "next-auth" {
interface Session {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Q: この辺りの各種interfaceはどこで利用しているものでしょうか?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

使っているのはpages/api/auth/[...nextauth].tsですね。この辺入れておかないと形エラーになってしまうので入れた気がします

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO: 分かりました。declare module "next-auth" が1つのファイルに複数あるメリットはないと思うので、まとめていただけるとありがたいです。

accessToken?: string;
}

interface OAuthConfig {
scope?: string;
params: {
grant_type: 'string'
}
}

interface Profile {
id?: string;
scope?: string;
}
}

declare module "next-auth/jwt" {
interface JWT {
accessToken?: string;
}
}

declare module 'next-auth' {}
Loading