63 lines
1.9 KiB
TypeScript
63 lines
1.9 KiB
TypeScript
import type { OAuthConfig, OAuthUserConfig } from "."
|
|
|
|
export interface AzureADProfile extends Record<string, any> {
|
|
sub: string
|
|
nickname: string
|
|
email: string
|
|
picture: string
|
|
}
|
|
|
|
export default function AzureAD<P extends AzureADProfile>(
|
|
options: OAuthUserConfig<P> & {
|
|
/**
|
|
* https://docs.microsoft.com/en-us/graph/api/profilephoto-get?view=graph-rest-1.0#examples
|
|
* @default 48
|
|
*/
|
|
profilePhotoSize?: 48 | 64 | 96 | 120 | 240 | 360 | 432 | 504 | 648
|
|
/** @default "common" */
|
|
tenantId?: string
|
|
}
|
|
): OAuthConfig<P> {
|
|
const tenant = options.tenantId ?? "common"
|
|
const profilePhotoSize = options.profilePhotoSize ?? 48
|
|
|
|
return {
|
|
id: "azure-ad",
|
|
name: "Azure Active Directory",
|
|
type: "oauth",
|
|
wellKnown: `https://login.microsoftonline.com/${tenant}/v2.0/.well-known/openid-configuration?appid=${options.clientId}`,
|
|
authorization: {
|
|
params: {
|
|
scope: "openid profile email",
|
|
},
|
|
},
|
|
async profile(profile, tokens) {
|
|
// https://docs.microsoft.com/en-us/graph/api/profilephoto-get?view=graph-rest-1.0#examples
|
|
const response = await fetch(
|
|
`https://graph.microsoft.com/v1.0/me/photos/${profilePhotoSize}x${profilePhotoSize}/$value`,
|
|
{ headers: { Authorization: `Bearer ${tokens.access_token}` } }
|
|
)
|
|
|
|
// Confirm that profile photo was returned
|
|
let image
|
|
// TODO: Do this without Buffer
|
|
if (response.ok && typeof Buffer !== "undefined") {
|
|
try {
|
|
const pictureBuffer = await response.arrayBuffer()
|
|
const pictureBase64 = Buffer.from(pictureBuffer).toString("base64")
|
|
image = `data:image/jpeg;base64, ${pictureBase64}`
|
|
} catch {}
|
|
}
|
|
|
|
return {
|
|
id: profile.sub,
|
|
name: profile.name,
|
|
email: profile.email,
|
|
image: image ?? null,
|
|
}
|
|
},
|
|
style: { logo: "/azure.svg", text: "#fff", bg: "#0072c6" },
|
|
options,
|
|
}
|
|
}
|