Skip to content

Commit

Permalink
fix: incorrect test
Browse files Browse the repository at this point in the history
  • Loading branch information
markusahlstrand committed Dec 15, 2024
1 parent 91a8f76 commit 2242489
Show file tree
Hide file tree
Showing 27 changed files with 1,014 additions and 57 deletions.
9 changes: 9 additions & 0 deletions apps/demo/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
# @authhero/demo

## 0.5.4

### Patch Changes

- Updated dependencies
- Updated dependencies
- [email protected]
- @authhero/kysely-adapter@0.25.3

## 0.5.3

### Patch Changes
Expand Down
6 changes: 3 additions & 3 deletions apps/demo/package.json
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
{
"name": "@authhero/demo",
"private": true,
"version": "0.5.3",
"version": "0.5.4",
"scripts": {
"dev": "bun --watch src/bun.ts"
},
"dependencies": {
"@authhero/kysely-adapter": "^0.25.1",
"@authhero/kysely-adapter": "^0.25.3",
"@hono/swagger-ui": "^0.5.0",
"@hono/zod-openapi": "^0.18.3",
"@peculiar/x509": "^1.12.3",
"authhero": "^0.25.0",
"authhero": "^0.26.0",
"hono": "^4.6.13",
"hono-openapi-middlewares": "^1.0.11",
"kysely-bun-sqlite": "^0.3.2",
Expand Down
7 changes: 7 additions & 0 deletions packages/adapter-interfaces/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# @authhero/adapter-interfaces

## 0.33.0

### Minor Changes

- add sendgrid and postmark mail services
- migrate dbconnections and setup email providers

## 0.32.1

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/adapter-interfaces/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"type": "git",
"url": "https://github.com/markusahlstrand/authhero"
},
"version": "0.32.1",
"version": "0.33.0",
"files": [
"dist"
],
Expand Down
4 changes: 1 addition & 3 deletions packages/adapter-interfaces/src/types/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ const ClientDomainSchema = z.object({
dkim_private_key: z.string().optional(),
dkim_public_key: z.string().optional(),
email_api_key: z.string().optional(),
email_service: z
.union([z.literal("mailgun"), z.literal("mailchannels")])
.optional(),
email_service: z.string().optional(),
});

const ClientSchema = z.object({
Expand Down
2 changes: 1 addition & 1 deletion packages/adapter-interfaces/src/types/Domain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ export const domainInsertSchema = z.object({
dkim_private_key: z.string().optional(),
dkim_public_key: z.string().optional(),
email_api_key: z.string().optional(),
email_service: z.enum(["mailgun", "mailchannels"]),
email_service: z.string().optional(),
});
export type DomainInsert = z.infer<typeof domainInsertSchema>;

Expand Down
13 changes: 13 additions & 0 deletions packages/authhero/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# authhero

## 0.26.0

### Minor Changes

- add id-token support to hook
- migrate dbconnections and setup email providers

### Patch Changes

- Updated dependencies
- Updated dependencies
- @authhero/adapter-interfaces@0.33.0

## 0.25.2

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion packages/authhero/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "authhero",
"version": "0.25.2",
"version": "0.26.0",
"files": [
"dist"
],
Expand Down
4 changes: 3 additions & 1 deletion packages/authhero/src/auth-app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
tokenRoutes,
wellKnownRoutes,
userinfoRoutes,
dbConnectionRoutes,
} from "./routes/auth-api";

export interface CreateAuthParams {
Expand All @@ -26,7 +27,8 @@ export default function create() {
.route("/v2/logout", logoutRoutes)
.route("/userinfo", userinfoRoutes)
.route("/.well-known", wellKnownRoutes)
.route("/oauth/token", tokenRoutes);
.route("/oauth/token", tokenRoutes)
.route("/dbconnections", dbConnectionRoutes);

oauthApp.doc("/spec", {
openapi: "3.0.0",
Expand Down
92 changes: 48 additions & 44 deletions packages/authhero/src/authentication-flows/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ export interface CreateAuthTokensParams {
sid?: string;
}

const RESERVED_CLAIMS = ["sub", "iss", "aud", "exp", "nbf", "iat", "jti"];

export async function createAuthTokens(
ctx: Context<{ Bindings: Bindings; Variables: Variables }>,
params: CreateAuthTokensParams,
Expand All @@ -31,7 +33,7 @@ export async function createAuthTokens(

const keyBuffer = pemToBuffer(signingKey.pkcs7);

const payload = {
const accessTokenPayload = {
// TODO: consider if the dafault should be removed
aud: authParams.audience || "default",
scope: authParams.scope || "",
Expand All @@ -41,6 +43,26 @@ export async function createAuthTokens(
sid,
};

const idTokenPayload =
user && authParams.scope?.split(" ").includes("openid")
? {
// The audience for an id token is the client id
aud: authParams.client_id,
sub: user.user_id,
iss: ctx.env.ISSUER,
sid,
nonce: authParams.nonce,
given_name: user.given_name,
family_name: user.family_name,
nickname: user.nickname,
picture: user.picture,
locale: user.locale,
name: user.name,
email: user.email,
email_verified: user.email_verified,
}
: undefined;

if (ctx.env.hooks?.onExecuteCredentialsExchange) {
await ctx.env.hooks.onExecuteCredentialsExchange(
{
Expand All @@ -52,19 +74,21 @@ export async function createAuthTokens(
{
accessToken: {
setCustomClaim: (claim, value) => {
const reservedClaims = [
"sub",
"iss",
"aud",
"exp",
"nbf",
"iat",
"jti",
];
if (reservedClaims.includes(claim)) {
if (RESERVED_CLAIMS.includes(claim)) {
throw new Error(`Cannot overwrite reserved claim '${claim}'`);
}
accessTokenPayload[claim] = value;
},
},
idToken: {
setCustomClaim: (claim, value) => {
if (RESERVED_CLAIMS.includes(claim)) {
throw new Error(`Cannot overwrite reserved claim '${claim}'`);
}
payload[claim] = value;

if (idTokenPayload) {
idTokenPayload[claim] = value;
}
},
},
access: {
Expand All @@ -78,44 +102,24 @@ export async function createAuthTokens(
);
}

const access_token = await createJWT("RS256", keyBuffer, payload, {
const header = {
includeIssuedTimestamp: true,
expiresIn: new TimeSpan(1, "d"),
headers: {
kid: signingKey.kid,
},
});
};

const id_token =
user && authParams.scope?.split(" ").includes("openid")
? await createJWT(
"RS256",
keyBuffer,
{
// The audience for an id token is the client id
aud: authParams.client_id,
sub: user.user_id,
iss: ctx.env.ISSUER,
sid,
nonce: authParams.nonce,
given_name: user.given_name,
family_name: user.family_name,
nickname: user.nickname,
picture: user.picture,
locale: user.locale,
name: user.name,
email: user.email,
email_verified: user.email_verified,
},
{
includeIssuedTimestamp: true,
expiresIn: new TimeSpan(1, "d"),
headers: {
kid: signingKey.kid,
},
},
)
: undefined;
const access_token = await createJWT(
"RS256",
keyBuffer,
accessTokenPayload,
header,
);

const id_token = idTokenPayload
? await createJWT("RS256", keyBuffer, idTokenPayload, header)
: undefined;

return {
access_token,
Expand Down
1 change: 1 addition & 0 deletions packages/authhero/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export const JWKS_CACHE_TIMEOUT_IN_SECONDS = 60 * 5; // 5 minutes
export const SILENT_AUTH_MAX_AGE = 30 * 24 * 60 * 60; // 30 days
export const UNIVERSAL_AUTH_SESSION_EXPIRES_IN_SECONDS = 24 * 60 * 60; // 1 day
export const SILENT_COOKIE_NAME = "auth-token";
61 changes: 61 additions & 0 deletions packages/authhero/src/emails/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { Context } from "hono";
import { Bindings, Variables } from "../types";
import { User } from "@authhero/adapter-interfaces";
import { HTTPException } from "hono/http-exception";

export async function sendEmail(
ctx: Context<{ Bindings: Bindings; Variables: Variables }>,
tenant_id: string,
to: string,
subject: string,
html: string,
) {
const emailProvider = await ctx.env.data.emailProviders.get(tenant_id);

if (!emailProvider) {
throw new HTTPException(500, { message: "Email provider not found" });
}

const emailService = ctx.env.emailProvders?.[emailProvider.name];
if (!emailService) {
throw new HTTPException(500, { message: "Email provider not found" });
}

emailService({
to,
from: emailProvider.default_from_address || `login@${ctx.env.ISSUER}`,
subject,
html,
});
}

export async function sendResetPassword(
ctx: Context<{ Bindings: Bindings; Variables: Variables }>,
tenant_id: string,
to: string,
// auth0 just has a ticket, but we have a code and a state
code: string,
state?: string,
) {
await sendEmail(
ctx,
tenant_id,
to,
`Reset your password`,
`Click here to reset your password: ${ctx.env.ISSUER}u/reset-password?state=${state}&code=${code}`,
);
}

export async function sendValidateEmailAddress(
ctx: Context<{ Bindings: Bindings; Variables: Variables }>,
tenant_id: string,
user: User,
) {
await sendEmail(
ctx,
tenant_id,
user.email,
`Validate your email address`,
`Click here to validate your email: ${ctx.env.ISSUER}u/validate-email`,
);
}
Loading

0 comments on commit 2242489

Please sign in to comment.