|
1 | 1 | import { NextRequest, NextResponse } from "next/server" |
2 | | -import { upsertUser, updateUserGithubAuth } from "@/lib/db/queries" |
| 2 | +import { upsertUser, setUserGithubTokens } from "@/lib/db/queries" |
3 | 3 | import { createSessionToken, getSessionCookieOptions } from "@/lib/auth" |
4 | 4 | import { encryptSecret } from "@/lib/security/encryption" |
5 | 5 |
|
@@ -100,11 +100,31 @@ export async function GET(request: NextRequest) { |
100 | 100 | return makeAuthErrorRedirect("github_token") |
101 | 101 | } |
102 | 102 |
|
103 | | - const accessToken = tokenData.access_token |
| 103 | + const accessToken: string | undefined = tokenData.access_token |
| 104 | + const refreshToken: string | undefined = tokenData.refresh_token |
| 105 | + const expiresIn: number | undefined = |
| 106 | + typeof tokenData.expires_in === "number" ? tokenData.expires_in : undefined |
| 107 | + const refreshTokenExpiresIn: number | undefined = |
| 108 | + typeof tokenData.refresh_token_expires_in === "number" |
| 109 | + ? tokenData.refresh_token_expires_in |
| 110 | + : undefined |
| 111 | + |
104 | 112 | if (!accessToken) { |
105 | 113 | console.error("GitHub OAuth token error: missing access token", tokenData) |
106 | 114 | return makeAuthErrorRedirect("github_token") |
107 | 115 | } |
| 116 | + if (!refreshToken || !expiresIn || !refreshTokenExpiresIn) { |
| 117 | + console.error( |
| 118 | + "GitHub OAuth token error: response missing refresh_token / expires_in fields. " + |
| 119 | + "Confirm that 'Expire user authorization tokens' is enabled on the GitHub App.", |
| 120 | + { |
| 121 | + hasRefreshToken: Boolean(refreshToken), |
| 122 | + hasExpiresIn: Boolean(expiresIn), |
| 123 | + hasRefreshTokenExpiresIn: Boolean(refreshTokenExpiresIn), |
| 124 | + } |
| 125 | + ) |
| 126 | + return makeAuthErrorRedirect("github_token") |
| 127 | + } |
108 | 128 |
|
109 | 129 | // Step 3: Fetch user profile from GitHub API |
110 | 130 | const userRes = await fetch("https://api.github.com/user", { |
@@ -134,15 +154,20 @@ export async function GET(request: NextRequest) { |
134 | 154 | }) |
135 | 155 |
|
136 | 156 | const encryptedAccessToken = encryptSecret(accessToken) |
137 | | - if (!encryptedAccessToken) { |
| 157 | + const encryptedRefreshToken = encryptSecret(refreshToken) |
| 158 | + if (!encryptedAccessToken || !encryptedRefreshToken) { |
138 | 159 | console.error( |
139 | | - "Failed to encrypt GitHub OAuth token: ENCRYPTION_KEY or SESSION_SECRET is missing" |
| 160 | + "Failed to encrypt GitHub OAuth tokens: ENCRYPTION_KEY or SESSION_SECRET is missing" |
140 | 161 | ) |
141 | 162 | return makeAuthErrorRedirect("server_config") |
142 | 163 | } |
143 | 164 |
|
144 | | - await updateUserGithubAuth(user.id, { |
| 165 | + const now = Date.now() |
| 166 | + await setUserGithubTokens(user.id, { |
145 | 167 | accessTokenEncrypted: encryptedAccessToken, |
| 168 | + accessTokenExpiresAt: new Date(now + expiresIn * 1000).toISOString(), |
| 169 | + refreshTokenEncrypted: encryptedRefreshToken, |
| 170 | + refreshTokenExpiresAt: new Date(now + refreshTokenExpiresIn * 1000).toISOString(), |
146 | 171 | tokenScopes: tokenData.scope ?? "", |
147 | 172 | }) |
148 | 173 |
|
|
0 commit comments