mirror of
https://github.com/Nezumi-2711/onedrive-vercel-index.git
synced 2026-09-22 05:32:01 +00:00
verify identity after oauth, closes #242
This commit is contained in:
+1
-1
@@ -4,6 +4,6 @@
|
||||
"redirectUri": "http://localhost",
|
||||
"authApi": "https://login.microsoftonline.com/common/oauth2/v2.0/token",
|
||||
"driveApi": "https://graph.microsoft.com/v1.0/me/drive",
|
||||
"scope": "Files.Read.All Files.ReadWrite.All offline_access",
|
||||
"scope": "user.read files.read.all offline_access",
|
||||
"directLink": "https://public.dm.files.1drv.com"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"userPrincipalName": "spencer.woo@outlook.com",
|
||||
"icon": "/icons/128.png",
|
||||
"title": "Spencer's OneDrive",
|
||||
"baseDirectory": "/Public",
|
||||
|
||||
@@ -23,6 +23,7 @@ import {
|
||||
faCheckCircle,
|
||||
} from '@fortawesome/free-regular-svg-icons'
|
||||
import {
|
||||
faCheck,
|
||||
faPlus,
|
||||
faMinus,
|
||||
faCopy as faCopySolid,
|
||||
@@ -89,6 +90,7 @@ library.add(
|
||||
faExclamationCircle,
|
||||
faExclamationTriangle,
|
||||
faHome,
|
||||
faCheck,
|
||||
faCheckCircle,
|
||||
...iconList
|
||||
)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
import axios from 'axios'
|
||||
import Head from 'next/head'
|
||||
import Image from 'next/image'
|
||||
import { useRouter } from 'next/router'
|
||||
@@ -9,7 +8,7 @@ import siteConfig from '../../config/site.json'
|
||||
import Navbar from '../../components/Navbar'
|
||||
import Footer from '../../components/Footer'
|
||||
|
||||
import { obfuscateToken, requestTokenWithAuthCode } from '../../utils/oAuthHandler'
|
||||
import { getAuthPersonInfo, requestTokenWithAuthCode, sendTokenToServer } from '../../utils/oAuthHandler'
|
||||
import { LoadingIcon } from '../../components/Loading'
|
||||
|
||||
export default function OAuthStep3({ accessToken, expiryTime, refreshToken, error, description, errorUri }) {
|
||||
@@ -27,48 +26,59 @@ export default function OAuthStep3({ accessToken, expiryTime, refreshToken, erro
|
||||
}, [expiryTimeLeft])
|
||||
|
||||
const [buttonContent, setButtonContent] = useState(
|
||||
<>
|
||||
<div>
|
||||
<span>Store tokens</span> <FontAwesomeIcon icon="key" />
|
||||
</>
|
||||
</div>
|
||||
)
|
||||
const [buttonError, setButtonError] = useState(false)
|
||||
|
||||
const sendAuthTokensToServer = async () => {
|
||||
setButtonError(false)
|
||||
setButtonContent(
|
||||
<>
|
||||
<div>
|
||||
<span>Storing tokens</span> <LoadingIcon className="animate-spin w-4 h-4 ml-1 inline" />
|
||||
</>
|
||||
</div>
|
||||
)
|
||||
|
||||
await axios
|
||||
.post(
|
||||
'/api',
|
||||
{
|
||||
obfuscatedAccessToken: obfuscateToken(accessToken),
|
||||
accessTokenExpiry: parseInt(expiryTime),
|
||||
obfuscatedRefreshToken: obfuscateToken(refreshToken),
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}
|
||||
// verify identity of the authenticated user with the Microsoft Graph API
|
||||
const { data, status } = await getAuthPersonInfo(accessToken)
|
||||
if (status !== 200) {
|
||||
setButtonError(true)
|
||||
setButtonContent(
|
||||
<div>
|
||||
<span>Error validating identify, restart</span> <FontAwesomeIcon icon="exclamation-circle" />
|
||||
</div>
|
||||
)
|
||||
.then(_ => {
|
||||
setButtonContent(
|
||||
<>
|
||||
<span>Stored! Going home...</span> <FontAwesomeIcon icon="check" />
|
||||
</>
|
||||
)
|
||||
return
|
||||
}
|
||||
if (data.userPrincipalName !== siteConfig.userPrincipalName) {
|
||||
setButtonError(true)
|
||||
setButtonContent(
|
||||
<div>
|
||||
<span>Do not pretend to be the site owner</span> <FontAwesomeIcon icon="exclamation-circle" />
|
||||
</div>
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
await sendTokenToServer(accessToken, refreshToken, expiryTime)
|
||||
.then(() => {
|
||||
setButtonError(false)
|
||||
setButtonContent(
|
||||
<div>
|
||||
<span>Stored! Going home...</span> <FontAwesomeIcon icon="check" />
|
||||
</div>
|
||||
)
|
||||
setTimeout(() => {
|
||||
router.push('/')
|
||||
}, 2000)
|
||||
})
|
||||
.catch(_ => {
|
||||
setButtonError(true)
|
||||
setButtonContent(
|
||||
<>
|
||||
<div>
|
||||
<span>Error storing the token</span> <FontAwesomeIcon icon="exclamation-circle" />
|
||||
</>
|
||||
</div>
|
||||
)
|
||||
})
|
||||
}
|
||||
@@ -168,7 +178,11 @@ export default function OAuthStep3({ accessToken, expiryTime, refreshToken, erro
|
||||
|
||||
<div className="text-right mb-2 mt-6">
|
||||
<button
|
||||
className="text-white bg-gradient-to-br from-green-500 to-teal-300 hover:bg-gradient-to-bl focus:ring-4 focus:ring-green-200 dark:focus:ring-green-800 font-medium rounded-lg text-sm px-4 py-2.5 text-center disabled:cursor-not-allowed disabled:grayscale"
|
||||
className={`text-white bg-gradient-to-br hover:bg-gradient-to-bl focus:ring-4 font-medium rounded-lg text-sm px-4 py-2.5 text-center ${
|
||||
buttonError
|
||||
? 'from-red-500 to-orange-400 focus:ring-red-200 dark:focus:ring-red-800'
|
||||
: 'from-green-500 to-teal-300 focus:ring-green-200 dark:focus:ring-green-800'
|
||||
}`}
|
||||
onClick={sendAuthTokensToServer}
|
||||
>
|
||||
{buttonContent}
|
||||
|
||||
+29
-2
@@ -19,7 +19,7 @@ export function revealObfuscatedToken(obfuscated: string): string {
|
||||
|
||||
// Generate the Microsoft OAuth 2.0 authorization URL, used for requesting the authorisation code
|
||||
export function generateAuthorisationUrl(): string {
|
||||
const { clientId, redirectUri, authApi } = apiConfig
|
||||
const { clientId, redirectUri, authApi, scope } = apiConfig
|
||||
const authUrl = authApi.replace('/token', '/authorize')
|
||||
|
||||
// Construct URL parameters for OAuth2
|
||||
@@ -27,7 +27,7 @@ export function generateAuthorisationUrl(): string {
|
||||
params.append('client_id', clientId)
|
||||
params.append('redirect_uri', redirectUri)
|
||||
params.append('response_type', 'code')
|
||||
params.append('scope', 'files.readwrite offline_access')
|
||||
params.append('scope', scope)
|
||||
params.append('response_mode', 'query')
|
||||
|
||||
return `${authUrl}?${params.toString()}`
|
||||
@@ -82,3 +82,30 @@ export async function requestTokenWithAuthCode(
|
||||
return { error, errorDescription: error_description, errorUri: error_uri }
|
||||
})
|
||||
}
|
||||
|
||||
// Verify the identity of the user with the access token and compare it with the userPrincipalName
|
||||
// in the Microsoft Graph API. If the userPrincipalName matches, proceed with token storing.
|
||||
export async function getAuthPersonInfo(accessToken: string) {
|
||||
const profileApi = apiConfig.driveApi.replace('/drive', '')
|
||||
return axios.get(profileApi, {
|
||||
headers: {
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
export async function sendTokenToServer(accessToken: string, refreshToken: string, expiryTime: string) {
|
||||
return await axios.post(
|
||||
'/api',
|
||||
{
|
||||
obfuscatedAccessToken: obfuscateToken(accessToken),
|
||||
accessTokenExpiry: parseInt(expiryTime),
|
||||
obfuscatedRefreshToken: obfuscateToken(refreshToken),
|
||||
},
|
||||
{
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user