diff --git a/.yarn/versions/f2947d6d.yml b/.yarn/versions/f2947d6d.yml
new file mode 100644
index 0000000..7da9216
--- /dev/null
+++ b/.yarn/versions/f2947d6d.yml
@@ -0,0 +1,7 @@
+releases:
+ "@typoas/cli": minor
+ "@typoas/generator": minor
+ "@typoas/runtime": minor
+
+declined:
+ - "@typoas/react-query"
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 520b94f..e9149e4 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,8 @@
## Unreleased
+- Add support for `openIdConnect` security scheme type (fixes [#69](https://github.com/Embraser01/typoas/pull/69)) [#70](https://github.com/Embraser01/typoas/pull/70)
+
---
## 4.0.0 - 2024-08-21
diff --git a/README.md b/README.md
index 5c6491f..8c02f68 100644
--- a/README.md
+++ b/README.md
@@ -18,14 +18,14 @@ Main features are:
- **React Query** integration
- Support for `allOf`, `oneOf` and `anyOf` schemas.
- Automatically convert `format: 'date-time'` to JS `Date`
-- Handle **API Key**, **HTTP Config** and **OAuth2**1 auth security schemes
+- Handle **API Key**, **HTTP Config**, **OAuth2**1 and **OIDC**1 auth security schemes
- JSDoc for schemas and operations
- Uses `fetch` api (can be customized)
- Non JSON content type support
- Small bundle size
- And more...
-> 1: OAuth2 scheme does not handle flows to retrieve an `accessToken`.
+> 1: OAuth2 and OpenIDConnect scheme do not handle flows to retrieve an `accessToken`.
> You need to provide your own `accessToken` through the `provider.getConfig()` function.
The project is split into 4 packages:
@@ -253,11 +253,12 @@ const ctx = createContext({
});
```
-It supports 4 types of security schemes:
+It supports 5 types of security schemes:
- `apiKey` mode
- `http` bearer and basic mode
- `oauth2` mode
+- `openIdConnect` mode
The `getConfig` function should return the configuration needed to authenticate the request. Returning `null` will skip the authentification.
diff --git a/packages/typoas-generator/src/generator/components/security-scheme.ts b/packages/typoas-generator/src/generator/components/security-scheme.ts
index b1d8de3..cfeb94f 100644
--- a/packages/typoas-generator/src/generator/components/security-scheme.ts
+++ b/packages/typoas-generator/src/generator/components/security-scheme.ts
@@ -52,6 +52,11 @@ export function createConfigTypeFromSecurityScheme(
case 'oauth2':
return createRuntimeRefType(ExportedRef.OAuth2SecurityAuthentication);
case 'openIdConnect':
+ return createRuntimeRefType(
+ ExportedRef.OpenIdConnectSecurityAuthentication,
+ );
+ default:
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
throw new Error(`Unsupported security scheme '${securityScheme.type}'`);
}
}
@@ -123,6 +128,15 @@ export function createRuntimeSecurityClass(
[factory.createObjectLiteralExpression(args), authProviderExpression],
);
case 'openIdConnect':
+ return factory.createNewExpression(
+ createRuntimeRefProperty(
+ ExportedRef.OpenIdConnectSecurityAuthentication,
+ ),
+ undefined,
+ [factory.createObjectLiteralExpression(args), authProviderExpression],
+ );
+ default:
+ // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
throw new Error(`Unsupported security scheme '${securityScheme.type}'`);
}
}
diff --git a/packages/typoas-generator/src/generator/utils/ref.ts b/packages/typoas-generator/src/generator/utils/ref.ts
index 20d7d85..5623258 100644
--- a/packages/typoas-generator/src/generator/utils/ref.ts
+++ b/packages/typoas-generator/src/generator/utils/ref.ts
@@ -14,6 +14,7 @@ export enum ExportedRef {
HttpBasicSecurityAuthentication = 'HttpBasicSecurityAuthentication',
HttpBearerSecurityAuthentication = 'HttpBearerSecurityAuthentication',
OAuth2SecurityAuthentication = 'OAuth2SecurityAuthentication',
+ OpenIdConnectSecurityAuthentication = 'OpenIdConnectSecurityAuthentication',
StatusResponse = 'StatusResponse',
BaseFetcherData = 'BaseFetcherData',
}
diff --git a/packages/typoas-runtime/src/auth/base.ts b/packages/typoas-runtime/src/auth/base.ts
index 14a247a..d2f8c03 100644
--- a/packages/typoas-runtime/src/auth/base.ts
+++ b/packages/typoas-runtime/src/auth/base.ts
@@ -15,3 +15,12 @@ export interface SecurityAuthentication {
export interface AuthProvider {
getConfig(): Promise | T | null;
}
+
+/**
+ * Configuration for the OAuth2 and OIDC authentication scheme.
+ */
+export type BaseFlowConfig = {
+ accessToken: string;
+ // Allow overriding the token type (default: Bearer)
+ tokenType?: string;
+};
diff --git a/packages/typoas-runtime/src/auth/index.ts b/packages/typoas-runtime/src/auth/index.ts
index 2c15d05..e1f8e09 100644
--- a/packages/typoas-runtime/src/auth/index.ts
+++ b/packages/typoas-runtime/src/auth/index.ts
@@ -3,3 +3,4 @@ export * from './api-key-auth';
export * from './http-auth-basic';
export * from './http-auth-bearer';
export * from './oauth2-auth';
+export * from './open-id-connect-auth';
diff --git a/packages/typoas-runtime/src/auth/oauth2-auth.ts b/packages/typoas-runtime/src/auth/oauth2-auth.ts
index e3ee032..79ad499 100644
--- a/packages/typoas-runtime/src/auth/oauth2-auth.ts
+++ b/packages/typoas-runtime/src/auth/oauth2-auth.ts
@@ -1,16 +1,14 @@
-import type { AuthProvider, SecurityAuthentication } from './base';
+import type {
+ AuthProvider,
+ BaseFlowConfig,
+ SecurityAuthentication,
+} from './base';
import type { RequestContext } from '../fetcher';
// We don't actually need to have any configuration for OAuth2
// because we only use the already generated accessToken.
export type OAuth2Configuration = Record;
-export type BaseFlowConfig = {
- accessToken: string;
- // Allow overriding the token type (default: Bearer)
- tokenType?: string;
-};
-
export class OAuth2SecurityAuthentication implements SecurityAuthentication {
constructor(
private config: OAuth2Configuration,
diff --git a/packages/typoas-runtime/src/auth/open-id-connect-auth.ts b/packages/typoas-runtime/src/auth/open-id-connect-auth.ts
new file mode 100644
index 0000000..b2cc3c0
--- /dev/null
+++ b/packages/typoas-runtime/src/auth/open-id-connect-auth.ts
@@ -0,0 +1,34 @@
+import type {
+ AuthProvider,
+ BaseFlowConfig,
+ SecurityAuthentication,
+} from './base';
+import type { RequestContext } from '../fetcher';
+
+// We don't actually need to have any configuration for OpenIdConnect
+// because we only use the already generated accessToken.
+export type OpenIdConnectConfiguration = Record;
+
+export class OpenIdConnectSecurityAuthentication
+ implements SecurityAuthentication
+{
+ constructor(
+ private config: OpenIdConnectConfiguration,
+ private provider?: AuthProvider,
+ ) {}
+
+ async applySecurityAuthentication(context: RequestContext): Promise {
+ if (!this.provider) return;
+
+ const res = await this.provider.getConfig();
+ if (res === null) {
+ return;
+ }
+
+ const { accessToken, tokenType } = res;
+ return context.setHeaderParam(
+ 'Authorization',
+ `${tokenType || 'Bearer'} ${accessToken}`,
+ );
+ }
+}
diff --git a/packages/typoas-runtime/src/context/types.ts b/packages/typoas-runtime/src/context/types.ts
index d77a1e4..171f82a 100644
--- a/packages/typoas-runtime/src/context/types.ts
+++ b/packages/typoas-runtime/src/context/types.ts
@@ -5,7 +5,11 @@ import {
SerializerOptions,
} from '../fetcher';
import type { TransformEntity } from '../transformers';
-import type { AuthProvider, SecurityAuthentication } from '../auth';
+import {
+ AuthProvider,
+ OpenIdConnectSecurityAuthentication,
+ SecurityAuthentication,
+} from '../auth';
import type { Transform } from '../transformers';
import type { BaseServerConfiguration } from '../configuration';
import type {
@@ -89,7 +93,9 @@ export type AuthProviderConfig =
? BearerAuthConfig
: T extends OAuth2SecurityAuthentication
? BaseFlowConfig
- : never;
+ : T extends OpenIdConnectSecurityAuthentication
+ ? BaseFlowConfig
+ : never;
export type ResponseHandler = {
transforms?: TransformEntity;