auth flow
This commit is contained in:
parent
ce09b18a6f
commit
1443d8d9b2
@ -1,7 +1,7 @@
|
|||||||
import { notFound } from 'next/navigation'
|
import { notFound } from 'next/navigation'
|
||||||
import { getServerSession } from 'next-auth/next';
|
import { getServerSession } from 'next-auth/next';
|
||||||
import { authOptions } from '@/app/api/auth/[...nextauth]/route';
|
import { authOptions } from '@/app/api/auth/[...nextauth]/route';
|
||||||
import { ResponsiveIframe } from '@/app/components/responsive-iframe';
|
import ResponsiveIframe from '@/app/components/responsive-iframe';
|
||||||
import { redirect } from 'next/navigation';
|
import { redirect } from 'next/navigation';
|
||||||
|
|
||||||
// Use environment variables for real service URLs
|
// Use environment variables for real service URLs
|
||||||
@ -62,7 +62,7 @@ export default async function SectionPage(props: { params: { section: string } }
|
|||||||
<ResponsiveIframe
|
<ResponsiveIframe
|
||||||
src={proxyUrl}
|
src={proxyUrl}
|
||||||
className="w-full h-full border-none"
|
className="w-full h-full border-none"
|
||||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
allowFullScreen={true}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)
|
)
|
||||||
|
|||||||
@ -1,6 +1,57 @@
|
|||||||
import NextAuth, { NextAuthOptions } from "next-auth";
|
import NextAuth, { NextAuthOptions } from "next-auth";
|
||||||
import KeycloakProvider from "next-auth/providers/keycloak";
|
import KeycloakProvider from "next-auth/providers/keycloak";
|
||||||
|
|
||||||
|
// Define Keycloak profile type
|
||||||
|
interface KeycloakProfile {
|
||||||
|
sub: string;
|
||||||
|
email?: string;
|
||||||
|
name?: string;
|
||||||
|
preferred_username?: string;
|
||||||
|
given_name?: string;
|
||||||
|
family_name?: string;
|
||||||
|
realm_access?: {
|
||||||
|
roles: string[];
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define custom profile type
|
||||||
|
interface CustomProfile {
|
||||||
|
id: string;
|
||||||
|
name?: string | null;
|
||||||
|
email?: string | null;
|
||||||
|
username: string;
|
||||||
|
first_name: string;
|
||||||
|
last_name: string;
|
||||||
|
role: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Declare module augmentation for NextAuth types
|
||||||
|
declare module "next-auth" {
|
||||||
|
interface Session {
|
||||||
|
user: {
|
||||||
|
id: string;
|
||||||
|
name?: string | null;
|
||||||
|
email?: string | null;
|
||||||
|
image?: string | null;
|
||||||
|
username: string;
|
||||||
|
first_name: string;
|
||||||
|
last_name: string;
|
||||||
|
role: string[];
|
||||||
|
};
|
||||||
|
accessToken?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface JWT {
|
||||||
|
sub?: string;
|
||||||
|
accessToken?: string;
|
||||||
|
refreshToken?: string;
|
||||||
|
role?: string[];
|
||||||
|
username?: string;
|
||||||
|
first_name?: string;
|
||||||
|
last_name?: string;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Simple, minimal implementation - NO REFRESH TOKEN LOGIC
|
// Simple, minimal implementation - NO REFRESH TOKEN LOGIC
|
||||||
export const authOptions: NextAuthOptions = {
|
export const authOptions: NextAuthOptions = {
|
||||||
providers: [
|
providers: [
|
||||||
@ -8,37 +59,69 @@ export const authOptions: NextAuthOptions = {
|
|||||||
clientId: process.env.KEYCLOAK_CLIENT_ID || "",
|
clientId: process.env.KEYCLOAK_CLIENT_ID || "",
|
||||||
clientSecret: process.env.KEYCLOAK_CLIENT_SECRET || "",
|
clientSecret: process.env.KEYCLOAK_CLIENT_SECRET || "",
|
||||||
issuer: process.env.KEYCLOAK_ISSUER || "",
|
issuer: process.env.KEYCLOAK_ISSUER || "",
|
||||||
|
profile(profile: any) {
|
||||||
|
// Extract roles from the profile
|
||||||
|
const roles = profile.realm_access?.roles || [];
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: profile.sub,
|
||||||
|
name: profile.name || profile.preferred_username,
|
||||||
|
email: profile.email,
|
||||||
|
image: null,
|
||||||
|
role: roles.map((role: string) => role.replace(/^ROLE_/, '').toLowerCase()),
|
||||||
|
first_name: profile.given_name || '',
|
||||||
|
last_name: profile.family_name || '',
|
||||||
|
username: profile.preferred_username || profile.email?.split('@')[0] || '',
|
||||||
|
};
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
],
|
],
|
||||||
session: {
|
session: {
|
||||||
strategy: "jwt",
|
strategy: "jwt",
|
||||||
maxAge: 8 * 60 * 60, // 8 hours only
|
maxAge: 8 * 60 * 60, // 8 hours
|
||||||
},
|
},
|
||||||
callbacks: {
|
callbacks: {
|
||||||
// Simple JWT callback - no refresh logic
|
async jwt({ token, account, profile }: any) {
|
||||||
async jwt({ token, account }) {
|
if (account && profile) {
|
||||||
if (account) {
|
// Just store access token and critical fields
|
||||||
// Initial sign-in, store tokens
|
|
||||||
token.accessToken = account.access_token;
|
token.accessToken = account.access_token;
|
||||||
token.sub = account.providerAccountId;
|
// Make sure roles are available
|
||||||
|
if (profile.role) {
|
||||||
|
token.role = profile.role;
|
||||||
|
token.username = profile.username || '';
|
||||||
|
token.first_name = profile.first_name || '';
|
||||||
|
token.last_name = profile.last_name || '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return token;
|
return token;
|
||||||
},
|
},
|
||||||
// Simple session callback
|
async session({ session, token }: any) {
|
||||||
async session({ session, token }) {
|
// Pass necessary info to the session
|
||||||
session.accessToken = token.accessToken;
|
session.accessToken = token.accessToken;
|
||||||
if (session.user) {
|
if (session.user) {
|
||||||
session.user.id = token.sub || "";
|
session.user.id = token.sub || "";
|
||||||
|
|
||||||
|
// Ensure roles are passed to the session
|
||||||
|
if (token.role) {
|
||||||
|
session.user.role = token.role;
|
||||||
|
session.user.username = token.username || '';
|
||||||
|
session.user.first_name = token.first_name || '';
|
||||||
|
session.user.last_name = token.last_name || '';
|
||||||
|
} else {
|
||||||
|
// Fallback roles
|
||||||
|
session.user.role = ["user"];
|
||||||
|
session.user.username = '';
|
||||||
|
session.user.first_name = '';
|
||||||
|
session.user.last_name = '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return session;
|
return session;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
// Redirect to signin page for any errors
|
|
||||||
pages: {
|
pages: {
|
||||||
signIn: '/signin',
|
signIn: '/signin',
|
||||||
error: '/signin',
|
error: '/signin',
|
||||||
},
|
},
|
||||||
// Set reasonable cookie options
|
|
||||||
cookies: {
|
cookies: {
|
||||||
sessionToken: {
|
sessionToken: {
|
||||||
name: 'next-auth.session-token',
|
name: 'next-auth.session-token',
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
import { getServerSession } from "next-auth/next";
|
import { getServerSession } from "next-auth/next";
|
||||||
import { authOptions } from "@/app/api/auth/[...nextauth]/route";
|
import { authOptions } from "@/app/api/auth/[...nextauth]/route";
|
||||||
import { redirect } from "next/navigation";
|
import { redirect } from "next/navigation";
|
||||||
import { ResponsiveIframe } from "@/app/components/responsive-iframe";
|
import ResponsiveIframe from "@/app/components/responsive-iframe";
|
||||||
|
|
||||||
export default async function Page() {
|
export default async function Page() {
|
||||||
const session = await getServerSession(authOptions);
|
const session = await getServerSession(authOptions);
|
||||||
@ -15,12 +15,12 @@ export default async function Page() {
|
|||||||
<div className="w-full h-full px-4 pt-12 pb-4">
|
<div className="w-full h-full px-4 pt-12 pb-4">
|
||||||
<ResponsiveIframe
|
<ResponsiveIframe
|
||||||
src={process.env.NEXT_PUBLIC_IFRAME_DRIVE_URL || ''}
|
src={process.env.NEXT_PUBLIC_IFRAME_DRIVE_URL || ''}
|
||||||
allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture"
|
|
||||||
className="relative"
|
className="relative"
|
||||||
style={{
|
style={{
|
||||||
marginTop: '-50px', // Adjust this value based on the Nextcloud navbar height
|
marginTop: '-50px', // Adjust this value based on the Nextcloud navbar height
|
||||||
height: 'calc(100% + 50px)' // Compensate for the negative margin
|
height: 'calc(100% + 50px)' // Compensate for the negative margin
|
||||||
}}
|
}}
|
||||||
|
allowFullScreen={true}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user