Cleanup
This commit is contained in:
parent
c3c09856bc
commit
b9e9b53941
@ -3,3 +3,12 @@
|
||||
- Parse the SAML Request
|
||||
- Create the SAML Response
|
||||
- Fix the certificate
|
||||
- Install prettify
|
||||
|
||||
// Start a session
|
||||
// Store the RelayState in the session
|
||||
// Parse the SAMLRequest
|
||||
// Validate the SAMLRequest
|
||||
// Create SAMLResponse
|
||||
// POST the SAMLResponse to ACS URL
|
||||
// Remove the RelayState from the session
|
||||
13
lib/env.ts
13
lib/env.ts
@ -1,6 +1,9 @@
|
||||
const config = {
|
||||
appUrl: process.env.APP_URL || 'http://localhost:4000',
|
||||
entityId: process.env.ENTITY_ID || 'http://saml.example.com',
|
||||
}
|
||||
const appUrl = process.env.APP_URL || 'http://localhost:4000';
|
||||
const entityId = process.env.ENTITY_ID || 'http://saml.example.com';
|
||||
const ssoUrl = `${appUrl}/saml/sso`;
|
||||
|
||||
export default config;
|
||||
export default {
|
||||
appUrl,
|
||||
entityId,
|
||||
ssoUrl,
|
||||
};
|
||||
@ -1,13 +1,9 @@
|
||||
import '../styles/globals.css'
|
||||
import type { AppProps } from 'next/app'
|
||||
import Layout from '../components/Layout'
|
||||
import 'rsuite/dist/rsuite.min.css';
|
||||
|
||||
function MyApp({ Component, pageProps }: AppProps) {
|
||||
return (
|
||||
<Layout>
|
||||
<Component {...pageProps} />
|
||||
</Layout>
|
||||
<Component {...pageProps} />
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@ -1,32 +0,0 @@
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { createCertificate, createIdPSSOUrl } from '../../../../utils';
|
||||
import { IdPMetadata } from '../../../../types';
|
||||
import config from '../../../../lib/env'
|
||||
|
||||
export default async function handler(
|
||||
req: NextApiRequest,
|
||||
res: NextApiResponse<IdPMetadata | string>
|
||||
) {
|
||||
|
||||
switch (req.method) {
|
||||
case 'GET':
|
||||
return await getMetadata();
|
||||
default:
|
||||
return res.status(405).end(`Method ${req.method} Not Allowed`);
|
||||
}
|
||||
|
||||
// Get metadata for an app
|
||||
async function getMetadata() {
|
||||
//const {id} = req.query;
|
||||
const appId = '0480c44e-f200-4f72-8af0-a5a57611fd2d';
|
||||
|
||||
const metadata = {
|
||||
certificate: await createCertificate(),
|
||||
fingerprint: '',
|
||||
sso_url: createIdPSSOUrl(appId),
|
||||
entity_id: config.entityId,
|
||||
}
|
||||
|
||||
return res.json(metadata);
|
||||
}
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
import type { NextApiRequest, NextApiResponse } from 'next';
|
||||
import { createCertificate, createIdPMetadataXML, createIdPSSOUrl } from '../../../../utils';
|
||||
import { createCertificate, createIdPMetadataXML } from '../../../../utils';
|
||||
import { IdPMetadata } from '../../../../types';
|
||||
import stream from 'stream';
|
||||
import { promisify } from 'util';
|
||||
@ -19,18 +19,16 @@ export default async function handler(
|
||||
return res.status(405).end(`Method ${req.method} Not Allowed`);
|
||||
}
|
||||
|
||||
// Download metadata for an app
|
||||
// Download metadata
|
||||
async function downloadMetadata() {
|
||||
const appId = '0480c44e-f200-4f72-8af0-a5a57611fd2d';
|
||||
|
||||
const xml = await createIdPMetadataXML({
|
||||
idpEntityId: config.entityId,
|
||||
idpSsoUrl: createIdPSSOUrl(appId),
|
||||
idpSsoUrl: config.ssoUrl,
|
||||
certificate: await createCertificate(),
|
||||
});
|
||||
|
||||
res.setHeader('Content-type', 'text/xml');
|
||||
res.setHeader('Content-Disposition', 'attachment; filename=metadata.xml');
|
||||
res.setHeader('Content-Disposition', 'attachment; filename=mock-saml-metadata.xml');
|
||||
|
||||
await pipeline(xml, res);
|
||||
}
|
||||
@ -1,44 +0,0 @@
|
||||
import prisma from '../../lib/prisma';
|
||||
import { GetServerSideProps } from 'next';
|
||||
import { App } from '../../types';
|
||||
import axios from 'axios';
|
||||
import { IdPMetadata } from '../../types';
|
||||
import React, { ChangeEvent, FormEvent, useState } from 'react';
|
||||
|
||||
// TODO: Remove this
|
||||
export const getServerSideProps: GetServerSideProps = async ({ params }) => {
|
||||
const app = await prisma.app.findUnique({
|
||||
where: {
|
||||
id: params?.id,
|
||||
}
|
||||
});
|
||||
|
||||
const metadata = await axios.get('http://localhost:4000/api/apps/metadata');
|
||||
|
||||
return {
|
||||
props: {
|
||||
app,
|
||||
metadata: metadata.data,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const ShowApp: React.FC<{app: App, metadata: IdPMetadata}> = ({app, metadata}) => {
|
||||
return (
|
||||
<div>
|
||||
<p>Id: {app.id}</p>
|
||||
<p>name: {app.name}</p>
|
||||
<p>acs_url: {app.acs_url}</p>
|
||||
<p>entity_id: {app.entity_id}</p>
|
||||
|
||||
<strong>Metadata</strong>
|
||||
<p>sso_url: {metadata.sso_url}</p>
|
||||
<p>entity_id: {metadata.entity_id}</p>
|
||||
<p>certificate: {metadata.certificate}</p>
|
||||
|
||||
<a href="/api/apps/metadata/download" className="px-3 py-2 text-white bg-red-500 rounded">Download Metadata</a>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default ShowApp;
|
||||
@ -1,60 +0,0 @@
|
||||
import axios from 'axios';
|
||||
import type { NextPage } from 'next';
|
||||
import { ChangeEvent, FormEvent, useState } from 'react';
|
||||
import Router from 'next/router';
|
||||
|
||||
const Apps: NextPage = () => {
|
||||
const [formData, setFormData] = useState({
|
||||
name: null,
|
||||
acs_url: null,
|
||||
entity_id: null,
|
||||
});
|
||||
|
||||
const handleInputChange = (e: ChangeEvent<HTMLInputElement>) => {
|
||||
setFormData({
|
||||
...formData,
|
||||
[e.target.name]: e.target.value.trim()
|
||||
});
|
||||
}
|
||||
|
||||
const createApp = async (e: FormEvent) => {
|
||||
e.preventDefault();
|
||||
|
||||
const { data: app } = await axios.post('/api/apps', {
|
||||
...formData
|
||||
});
|
||||
|
||||
await Router.push(`/apps/${app.id}`);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<form onSubmit={createApp} className="px-8 pt-6 pb-8 mb-4 bg-white rounded shadow-md">
|
||||
<div className="mb-4">
|
||||
<label className="block mb-2 text-sm">
|
||||
App Name
|
||||
<input type="text" name="name" onChange={handleInputChange} required className="w-full px-3 py-2 border rounded" placeholder="App Name" />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<label className="block mb-2 text-sm">
|
||||
ACS URL
|
||||
<input type="text" name="acs_url" onChange={handleInputChange} required className="w-full px-3 py-2 border rounded" placeholder="ACS URL" />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div className="mb-4">
|
||||
<label className="block mb-2 text-sm">
|
||||
Entity ID
|
||||
<input type="text" name="entity_id" onChange={handleInputChange} required className="w-full px-3 py-2 border rounded" placeholder="Entity ID" />
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<button type="submit" className="px-4 py-2 text-white bg-blue-500 rounded">Create App</button>
|
||||
</form>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Apps;
|
||||
@ -1,70 +1,34 @@
|
||||
import type { NextPage } from 'next'
|
||||
import Head from 'next/head'
|
||||
import Image from 'next/image'
|
||||
import styles from '../styles/Home.module.css'
|
||||
import { GetServerSideProps } from 'next';
|
||||
import { IdPMetadata } from '../types'
|
||||
import config from '../lib/env';
|
||||
import {createCertificate} from '../utils'
|
||||
import React from 'react';
|
||||
import Link from 'next/link'
|
||||
|
||||
const Home: NextPage = () => {
|
||||
export const getServerSideProps: GetServerSideProps = async () => {
|
||||
const metadata: IdPMetadata = {
|
||||
ssoUrl: config.ssoUrl,
|
||||
entityId: config.entityId,
|
||||
certificate: await createCertificate(),
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
metadata
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
const Home: React.FC<{metadata: IdPMetadata}> = ({ metadata }) => {
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<Head>
|
||||
<title>Create Next App</title>
|
||||
<meta name="description" content="Generated by create next app" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
</Head>
|
||||
|
||||
<main className={styles.main}>
|
||||
<h1 className={styles.title}>
|
||||
Welcome to <a href="https://nextjs.org">Next.js!</a>
|
||||
</h1>
|
||||
|
||||
<p className={styles.description}>
|
||||
Get started by editing{' '}
|
||||
<code className={styles.code}>pages/index.tsx</code>
|
||||
</p>
|
||||
|
||||
<div className={styles.grid}>
|
||||
<a href="https://nextjs.org/docs" className={styles.card}>
|
||||
<h2>Documentation →</h2>
|
||||
<p>Find in-depth information about Next.js features and API.</p>
|
||||
</a>
|
||||
|
||||
<a href="https://nextjs.org/learn" className={styles.card}>
|
||||
<h2>Learn →</h2>
|
||||
<p>Learn about Next.js in an interactive course with quizzes!</p>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://github.com/vercel/next.js/tree/master/examples"
|
||||
className={styles.card}
|
||||
>
|
||||
<h2>Examples →</h2>
|
||||
<p>Discover and deploy boilerplate example Next.js projects.</p>
|
||||
</a>
|
||||
|
||||
<a
|
||||
href="https://vercel.com/new?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
|
||||
className={styles.card}
|
||||
>
|
||||
<h2>Deploy →</h2>
|
||||
<p>
|
||||
Instantly deploy your Next.js site to a public URL with Vercel.
|
||||
</p>
|
||||
</a>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer className={styles.footer}>
|
||||
<a
|
||||
href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
Powered by{' '}
|
||||
<span className={styles.logo}>
|
||||
<Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} />
|
||||
</span>
|
||||
</a>
|
||||
</footer>
|
||||
<div>
|
||||
<strong>Mock IdP Metadata</strong>
|
||||
<p>SSO URL: {metadata.ssoUrl}</p>
|
||||
<p>Entity ID: {metadata.entityId}</p>
|
||||
<p>Certificate: {metadata.certificate}</p>
|
||||
<br></br>
|
||||
<p><Link href="/api/saml/metadata/download">Download Metadata</Link></p>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
import type { GetServerSideProps } from 'next';
|
||||
import React from "react";
|
||||
import { AuthNRequest } from '../../../types'
|
||||
import {extractSAMLRequestAttributes} from '../../../utils'
|
||||
import { AuthNRequest } from '../../types'
|
||||
import { extractSAMLRequestAttributes } from '../../utils'
|
||||
|
||||
export const getServerSideProps: GetServerSideProps = async ({query, params}) => {
|
||||
const relayState = query.RelayState as string;
|
||||
const samlRequest = query.SAMLRequest as string;
|
||||
const samlRequest = query.SAMLRequest as string;
|
||||
|
||||
const attributes = await extractSAMLRequestAttributes(samlRequest);
|
||||
|
||||
@ -20,19 +20,9 @@ export const getServerSideProps: GetServerSideProps = async ({query, params}) =>
|
||||
}
|
||||
|
||||
const ProcessRequest: React.FC<AuthNRequest> = ({relayState, samlRequest}) => {
|
||||
|
||||
|
||||
return (
|
||||
<div>Process Request</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default ProcessRequest;
|
||||
|
||||
// Start a session
|
||||
// Store the RelayState in the session
|
||||
// Parse the SAMLRequest
|
||||
// Validate the SAMLRequest
|
||||
// Create SAMLResponse
|
||||
// POST the SAMLResponse to ACS URL
|
||||
// Remove the RelayState from the session
|
||||
export default ProcessRequest;
|
||||
0
pages/saml/sso.tsx
Normal file
0
pages/saml/sso.tsx
Normal file
@ -4,8 +4,8 @@ export type ServiceProvider = {
|
||||
};
|
||||
|
||||
export type IdentityProvider = {
|
||||
sso_url: string;
|
||||
entity_id: string;
|
||||
ssoUrl: string;
|
||||
entityId: string;
|
||||
};
|
||||
|
||||
export type App = {
|
||||
|
||||
@ -76,10 +76,6 @@ const createSAMLResponseXML = async (user: User): Promise<string> => {
|
||||
.replace('user_lastName', 'K');
|
||||
};
|
||||
|
||||
const createIdPSSOUrl = (appId: string) => {
|
||||
return `${config.appUrl}/saml2/apps/${appId}`;
|
||||
}
|
||||
|
||||
export {
|
||||
parseXML,
|
||||
extractSAMLRequestAttributes,
|
||||
@ -87,5 +83,4 @@ export {
|
||||
createSAMLResponseXML,
|
||||
createCertificate,
|
||||
extractCert,
|
||||
createIdPSSOUrl,
|
||||
};
|
||||
Loading…
Reference in New Issue
Block a user