Idp login (#13)

* Support IdP login

* added ldP login link

* tweaked layout

* redirectUrl -> acsUrl

* Added secondary button class

* Style and layout tweaks

* Add aria-hidden to svg

Co-authored-by: Aswin V <vaswin91@gmail.com>
This commit is contained in:
Deepak Prabhakara 2022-03-03 18:40:32 +00:00 committed by GitHub
parent d1f6cba776
commit 60c1fe9bf9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 100 additions and 37 deletions

View File

@ -5,7 +5,7 @@ export default function Header() {
<header className='body-font text-gray-600'> <header className='body-font text-gray-600'>
<div className='container mx-auto flex flex-col flex-wrap items-center p-5 md:flex-row'> <div className='container mx-auto flex flex-col flex-wrap items-center p-5 md:flex-row'>
<Link href='/'> <Link href='/'>
<a className='title-font mb-4 flex items-center font-medium text-gray-900 md:mb-0'> <a className='title-font flex items-center font-medium text-gray-900 md:mb-0'>
<svg <svg
xmlns='http://www.w3.org/2000/svg' xmlns='http://www.w3.org/2000/svg'
fill='none' fill='none'
@ -17,11 +17,12 @@ export default function Header() {
viewBox='0 0 24 24'> viewBox='0 0 24 24'>
<path d='M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5' /> <path d='M12 2L2 7l10 5 10-5-10-5zM2 17l10 5 10-5M2 12l10 5 10-5' />
</svg> </svg>
<span className='ml-3 text-xl'>Mock SAML</span> <span className='ml-3 text-2xl'>Mock SAML</span>
</a> </a>
</Link> </Link>
<span className='ml-2 text-sm text-gray-500'> <nav className='mt-2 flex flex-col flex-wrap items-center text-base md:ml-auto md:mt-0 md:items-end'>
Powered by <span className='ml-2 text-sm text-gray-500 '>
Made with <span className='text-[#e25555]'>&#9829;</span>
<a <a
href='https://boxyhq.com/' href='https://boxyhq.com/'
className='ml-1 text-gray-600' className='ml-1 text-gray-600'
@ -30,9 +31,8 @@ export default function Header() {
<strong>BoxyHQ</strong> <strong>BoxyHQ</strong>
</a> </a>
</span> </span>
<nav className='flex flex-wrap items-center justify-center text-base md:ml-auto'>
<a <a
className='mr-5 underline hover:text-gray-900' className='leading-5 underline hover:text-gray-900'
href='https://github.com/boxyhq/jackson' href='https://github.com/boxyhq/jackson'
rel='noopener noreferrer' rel='noopener noreferrer'
target='_blank'> target='_blank'>

View File

@ -23,39 +23,58 @@ const Home: React.FC<{ metadata: IdPMetadata }> = ({ metadata }) => {
return ( return (
<section className='body-font text-gray-600'> <section className='body-font text-gray-600'>
<div className='container mx-auto px-5 py-24'> <div className='container mx-auto px-5 py-8'>
<div className='mb-12 flex w-full flex-col text-center'> <div className='mb-5 flex w-full flex-col text-center'>
<h1 className='title-font mb-4 text-2xl font-medium text-gray-900 sm:text-3xl'>
Mock SAML Metadata
</h1>
<p className='mx-auto text-lg font-medium leading-relaxed lg:w-2/3'> <p className='mx-auto text-lg font-medium leading-relaxed lg:w-2/3'>
A free SAML 2.0 Identity Provider for testing SAML SSO integrations. A free SAML 2.0 Identity Provider for testing SAML SSO integrations.
<sup className='text-xl text-orange-600'>*</sup>
</p> </p>
<p> <div className='mx-auto mt-4 flex w-full justify-center px-8 lg:w-2/3'>
<b>Please do not use this in production.</b> <Link href='/saml/login'>
</p> <a className='button min-w-[14rem] py-3 text-xl tracking-wide'>Test IdP Login</a>
</Link>
</div> </div>
<div className='mx-auto flex w-full items-end space-y-4 px-8 sm:space-x-4 sm:space-y-0 sm:px-0 lg:w-2/3'> </div>
<div className='relative mr-4 lg:w-full'> <h2 className='title-font mt-9 text-center text-lg font-medium text-gray-900 sm:text-3xl'>
Mock SAML Metadata
</h2>
<div className='mx-auto mt-5 flex w-full space-x-6 px-8 lg:w-2/3'>
<div className='relative flex-1'>
<label className='text-sm leading-7 text-gray-600'>SSO URL</label> <label className='text-sm leading-7 text-gray-600'>SSO URL</label>
<input readOnly type='text' defaultValue={ssoUrl} className='input w-full' /> <input readOnly type='text' defaultValue={ssoUrl} className='input w-full' />
</div> </div>
<div className='relative mr-4 lg:w-full'> <div className='relative flex-1'>
<label className='text-sm leading-7 text-gray-600'>Entity ID</label> <label className='text-sm leading-7 text-gray-600'>Entity ID</label>
<input readOnly type='text' defaultValue={entityId} className='input w-full' /> <input readOnly type='text' defaultValue={entityId} className='input w-full' />
</div> </div>
</div> </div>
<div className='mx-auto mt-5 flex w-full items-end space-y-4 px-8 sm:space-x-4 sm:space-y-0 sm:px-0 lg:w-2/3'> <div className='mx-auto mt-5 flex w-full px-8 lg:w-2/3'>
<div className='relative lg:w-full'> <div className='relative w-full'>
<label className='text-sm leading-7 text-gray-600'>Certificate</label> <label className='text-sm leading-7 text-gray-600'>Certificate</label>
<textarea readOnly rows={5} defaultValue={certificate} className='input w-full'></textarea> <textarea readOnly rows={5} defaultValue={certificate} className='input w-full'></textarea>
</div> </div>
</div> </div>
<div className='mx-auto mt-5 flex w-full items-end space-y-4 px-8 sm:space-x-4 sm:space-y-0 sm:px-0 lg:w-2/3'> <div className='mx-auto mt-5 flex w-full justify-center px-8 lg:w-2/3'>
<Link href='/api/saml/metadata/download'> <Link href='/api/saml/metadata/download'>
<a className='button'>Download Metadata</a> <a className='button-secondary'>
<svg
className='mr-1 inline-block h-6 w-6'
fill='none'
viewBox='0 0 24 24'
stroke='currentColor'
aria-hidden
strokeWidth='2'>
<path
strokeLinecap='round'
strokeLinejoin='round'
d='M4 16v1a3 3 0 003 3h10a3 3 0 003-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4'
/>
</svg>
Download Metadata
</a>
</Link> </Link>
</div> </div>
<p className='mt-3 text-center text-lg text-orange-600'>* Caution: Not for production use</p>
</div> </div>
</section> </section>
); );

View File

@ -10,14 +10,20 @@ export default function Login() {
const [state, setState] = useState({ const [state, setState] = useState({
username: 'jackson', username: 'jackson',
domain: 'example.com', domain: 'example.com',
acsUrl: 'https://jackson-demo.boxyhq.com/api/oauth/saml',
audience: 'https://saml.boxyhq.com',
}); });
const acsUrlInp = useRef<HTMLInputElement>(null);
// Set focus to email input on load // Set focus to email input on load
const emailInp = useRef<HTMLInputElement>(null); const emailInp = useRef<HTMLInputElement>(null);
useEffect(() => { useEffect(() => {
if (emailInp.current) { if (acsUrl && emailInp.current) {
emailInp.current.focus(); emailInp.current.focus();
emailInp.current.select(); emailInp.current.select();
} else if (acsUrlInp.current) {
acsUrlInp.current.focus();
acsUrlInp.current.select();
} }
}, []); }, []);
@ -43,8 +49,8 @@ export default function Login() {
body: JSON.stringify({ body: JSON.stringify({
email: `${username}@${domain}`, email: `${username}@${domain}`,
id, id,
audience, audience: audience || state.audience,
acsUrl, acsUrl: acsUrl || state.acsUrl,
providerName, providerName,
relayState, relayState,
}), }),
@ -69,7 +75,42 @@ export default function Login() {
<div className='relative top-20 mx-auto w-[465px] max-w-[90%] rounded-md border p-10 text-[#145698]'> <div className='relative top-20 mx-auto w-[465px] max-w-[90%] rounded-md border p-10 text-[#145698]'>
<h2 className='mb-3 text-center text-3xl font-bold'>Login</h2> <h2 className='mb-3 text-center text-3xl font-bold'>Login</h2>
<form onSubmit={handleSubmit}> <form onSubmit={handleSubmit}>
<div className='flex items-end gap-x-1'> {acsUrl ? null : (
<div>
<div className='mt-5'>
<label htmlFor='acsUrl' className='mb-2 block'>
ACS URL <sup>(This is where we'll post the SAML Response)</sup>
</label>
<input
name='acsUrl'
id='acsUrl'
ref={acsUrlInp}
autoComplete='off'
type='text'
placeholder='https://jackson-demo.boxyhq.com/api/oauth/saml'
value={state.acsUrl}
onChange={handleChange}
className='input w-full'
/>
</div>
<div className='mt-5'>
<label htmlFor='audience' className='mb-2 block'>
Audience
</label>
<input
name='audience'
id='audience'
autoComplete='off'
type='text'
placeholder='https://saml.boxyhq.com'
value={state.audience}
onChange={handleChange}
className='input w-full'
/>
</div>
</div>
)}
<div className='mt-5 flex items-end gap-x-1'>
<div> <div>
<label htmlFor='username' className='mb-2 block'> <label htmlFor='username' className='mb-2 block'>
Email Email
@ -84,7 +125,7 @@ export default function Login() {
value={state.username} value={state.username}
onChange={handleChange} onChange={handleChange}
className='input' className='input'
title='please provide a mock example.com email address' title='Please provide a mock email address'
/> />
</div> </div>
<select <select
@ -99,11 +140,10 @@ export default function Login() {
</div> </div>
<div className='mt-5'> <div className='mt-5'>
<label htmlFor='password' className='mb-2 block'> <label htmlFor='password' className='mb-2 block'>
Password <sup>(Prefilled for you)</sup> Password <sup>(Any password works)</sup>
</label> </label>
<input <input
id='password' id='password'
readOnly={true}
autoComplete='off' autoComplete='off'
type='password' type='password'
defaultValue='samlstrongpassword' defaultValue='samlstrongpassword'

View File

@ -26,7 +26,11 @@ a {
@layer components { @layer components {
.button { .button {
@apply block rounded-md bg-indigo-500 px-4 py-2 leading-8 text-white shadow-md hover:bg-indigo-600 focus:outline-none focus:ring-4 focus:ring-indigo-300 focus:ring-opacity-100; @apply block rounded-md bg-indigo-500 px-4 py-2 leading-8 text-white shadow-md hover:bg-indigo-600 focus:bg-indigo-600 focus:outline-none focus:ring-4 focus:ring-indigo-300 focus:ring-opacity-100;
}
.button-secondary {
@apply button border-2 border-indigo-800 bg-white text-indigo-500 hover:bg-white hover:shadow-lg focus:bg-white;
} }
.input { .input {