-
Notifications
You must be signed in to change notification settings - Fork 35
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #35 from zitadel/idp-register
IDP register
- Loading branch information
Showing
53 changed files
with
2,883 additions
and
2,117 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,3 +17,5 @@ packages/zitadel-server/src/app/proto | |
packages/zitadel-client/src/app/proto | ||
.vscode | ||
.idea | ||
.vercel | ||
.env*.local |
133 changes: 133 additions & 0 deletions
133
apps/login/app/(login)/register/idp/[provider]/success/page.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
import { ProviderSlug } from "#/lib/demos"; | ||
import { addHumanUser, server } from "#/lib/zitadel"; | ||
import Alert, { AlertType } from "#/ui/Alert"; | ||
import { | ||
AddHumanUserRequest, | ||
IDPInformation, | ||
RetrieveIdentityProviderInformationResponse, | ||
user, | ||
IDPLink, | ||
} from "@zitadel/server"; | ||
|
||
const PROVIDER_MAPPING: { | ||
[provider: string]: (rI: IDPInformation) => Partial<AddHumanUserRequest>; | ||
} = { | ||
[ProviderSlug.GOOGLE]: (idp: IDPInformation) => { | ||
const idpLink: IDPLink = { | ||
idpId: idp.idpId, | ||
userId: idp.userId, | ||
userName: idp.userName, | ||
}; | ||
const req: Partial<AddHumanUserRequest> = { | ||
username: idp.userName, | ||
email: { | ||
email: idp.rawInformation?.User?.email, | ||
isVerified: true, | ||
}, | ||
// organisation: Organisation | undefined; | ||
profile: { | ||
displayName: idp.rawInformation?.User?.name ?? "", | ||
firstName: idp.rawInformation?.User?.given_name ?? "", | ||
lastName: idp.rawInformation?.User?.family_name ?? "", | ||
}, | ||
idpLinks: [idpLink], | ||
}; | ||
return req; | ||
}, | ||
[ProviderSlug.GITHUB]: (idp: IDPInformation) => { | ||
const idpLink: IDPLink = { | ||
idpId: idp.idpId, | ||
userId: idp.userId, | ||
userName: idp.userName, | ||
}; | ||
const req: Partial<AddHumanUserRequest> = { | ||
username: idp.userName, | ||
email: { | ||
email: idp.rawInformation?.email, | ||
isVerified: true, | ||
}, | ||
// organisation: Organisation | undefined; | ||
profile: { | ||
displayName: idp.rawInformation?.name ?? "", | ||
firstName: idp.rawInformation?.name ?? "", | ||
lastName: idp.rawInformation?.name ?? "", | ||
}, | ||
idpLinks: [idpLink], | ||
}; | ||
return req; | ||
}, | ||
}; | ||
|
||
function retrieveIDP( | ||
id: string, | ||
token: string | ||
): Promise<IDPInformation | undefined> { | ||
const userService = user.getUser(server); | ||
return userService | ||
.retrieveIdentityProviderInformation({ intentId: id, token: token }, {}) | ||
.then((resp: RetrieveIdentityProviderInformationResponse) => { | ||
return resp.idpInformation; | ||
}); | ||
} | ||
|
||
function createUser( | ||
provider: ProviderSlug, | ||
info: IDPInformation | ||
): Promise<string> { | ||
const userData = PROVIDER_MAPPING[provider](info); | ||
const userService = user.getUser(server); | ||
return userService.addHumanUser(userData, {}).then((resp) => resp.userId); | ||
} | ||
|
||
export default async function Page({ | ||
searchParams, | ||
params, | ||
}: { | ||
searchParams: Record<string | number | symbol, string | undefined>; | ||
params: { provider: ProviderSlug }; | ||
}) { | ||
const { id, token } = searchParams; | ||
const { provider } = params; | ||
|
||
if (provider && id && token) { | ||
return retrieveIDP(id, token) | ||
.then((information) => { | ||
if (information) { | ||
return createUser(provider, information).catch((error) => { | ||
throw new Error(error.details); | ||
}); | ||
} else { | ||
throw new Error("Could not get user information."); | ||
} | ||
}) | ||
.then((userId) => { | ||
return ( | ||
<div className="flex flex-col items-center space-y-4"> | ||
<h1>Register successful</h1> | ||
<div>You have successfully been registered!</div> | ||
</div> | ||
); | ||
}) | ||
.catch((error: Error) => { | ||
return ( | ||
<div className="flex flex-col items-center space-y-4"> | ||
<h1>Register failed</h1> | ||
<div className="w-full"> | ||
{ | ||
<Alert type={AlertType.ALERT}> | ||
{JSON.stringify(error.message)} | ||
</Alert> | ||
} | ||
</div> | ||
</div> | ||
); | ||
}); | ||
} else { | ||
return ( | ||
<div className="flex flex-col items-center space-y-4"> | ||
<h1>Register</h1> | ||
<p className="ztdl-p">No id and token received!</p> | ||
</div> | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import { getLegalAndSupportSettings, server } from "#/lib/zitadel"; | ||
import { SignInWithIDP } from "#/ui/SignInWithIDP"; | ||
import { | ||
GetActiveIdentityProvidersResponse, | ||
IdentityProvider, | ||
ZitadelServer, | ||
settings, | ||
} from "@zitadel/server"; | ||
|
||
function getIdentityProviders( | ||
server: ZitadelServer, | ||
orgId?: string | ||
): Promise<IdentityProvider[] | undefined> { | ||
const settingsService = settings.getSettings(server); | ||
return settingsService | ||
.getActiveIdentityProviders( | ||
orgId ? { ctx: { orgId } } : { ctx: { instance: true } }, | ||
{} | ||
) | ||
.then((resp: GetActiveIdentityProvidersResponse) => { | ||
return resp.identityProviders; | ||
}); | ||
} | ||
|
||
export default async function Page() { | ||
const legal = await getLegalAndSupportSettings(server); | ||
|
||
// TODO if org idps should be shown replace emptystring with the orgId. | ||
const identityProviders = await getIdentityProviders(server, ""); | ||
|
||
const host = process.env.VERCEL_URL | ||
? `https://${process.env.VERCEL_URL}` | ||
: "http://localhost:3000"; | ||
|
||
return ( | ||
<div className="flex flex-col items-center space-y-4"> | ||
<h1>Register</h1> | ||
<p className="ztdl-p"> | ||
Select one of the following providers to register | ||
</p> | ||
|
||
{legal && identityProviders && process.env.ZITADEL_API_URL && ( | ||
<SignInWithIDP | ||
host={host} | ||
identityProviders={identityProviders} | ||
></SignInWithIDP> | ||
)} | ||
</div> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { server, startIdentityProviderFlow } from "#/lib/zitadel"; | ||
import { NextRequest, NextResponse } from "next/server"; | ||
|
||
export async function POST(request: NextRequest) { | ||
const body = await request.json(); | ||
if (body) { | ||
let { idpId, successUrl, failureUrl } = body; | ||
|
||
return startIdentityProviderFlow(server, { idpId, successUrl, failureUrl }) | ||
.then((resp) => { | ||
return NextResponse.json(resp); | ||
}) | ||
.catch((error) => { | ||
return NextResponse.json(error, { status: 500 }); | ||
}); | ||
} else { | ||
return NextResponse.json({}, { status: 400 }); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { stub } from "../support/mock"; | ||
|
||
const IDP_URL = "https://example.com/idp/url"; | ||
|
||
describe("register idps", () => { | ||
beforeEach(() => { | ||
stub("zitadel.user.v2alpha.UserService", "StartIdentityProviderFlow", { | ||
data: { | ||
authUrl: IDP_URL, | ||
}, | ||
}); | ||
}); | ||
|
||
it("should redirect the user to the correct url", () => { | ||
cy.visit("/register/idp"); | ||
cy.get('button[e2e="google"]').click(); | ||
cy.origin(IDP_URL, { args: IDP_URL }, (url) => { | ||
cy.location("href", { timeout: 10_000 }).should("eq", url); | ||
}); | ||
}); | ||
}); |
Oops, something went wrong.
b330367
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Successfully deployed to the following URLs:
typescript-login – ./
typescript-login-git-main-zitadel.vercel.app
typescript-login-zitadel.vercel.app
typescript-login.vercel.app