feat: support client_secret
This commit is contained in:
parent
144e4c2f97
commit
0d957dfb1c
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "oidc-client-rx",
|
"name": "oidc-client-rx",
|
||||||
"version": "0.1.0-alpha.4",
|
"version": "0.1.0-alpha.5",
|
||||||
"homepage": "https://github.com/lonelyhentxi/oidc-client-rx",
|
"homepage": "https://github.com/lonelyhentxi/oidc-client-rx",
|
||||||
"author": "lonelyhentxi",
|
"author": "lonelyhentxi",
|
||||||
"description": "ReactiveX enhanced OIDC and OAuth2 protocol support for browser-based JavaScript applications",
|
"description": "ReactiveX enhanced OIDC and OAuth2 protocol support for browser-based JavaScript applications",
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { InjectionToken, inject } from '@outposts/injection-js';
|
import { InjectionToken, inject } from '@outposts/injection-js';
|
||||||
import type { Router } from '@tanstack/react-router';
|
import type { AnyRouter } from '@tanstack/react-router';
|
||||||
import type { AuthFeature } from '../../features';
|
import type { AuthFeature } from '../../features';
|
||||||
import { AbstractRouter } from '../../router';
|
import { AbstractRouter } from '../../router';
|
||||||
|
|
||||||
export type TanStackRouter = Router<any, any, any, any, any, any>;
|
export type TanStackRouter = AnyRouter;
|
||||||
|
|
||||||
export const TANSTACK_ROUTER = new InjectionToken<TanStackRouter>(
|
export const TANSTACK_ROUTER = new InjectionToken<TanStackRouter>(
|
||||||
'TANSTACK_ROUTER'
|
'TANSTACK_ROUTER'
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import { Injectable, inject } from '@outposts/injection-js';
|
import { Injectable, inject } from '@outposts/injection-js';
|
||||||
import type { Observable } from 'rxjs';
|
import { type Observable, of } from 'rxjs';
|
||||||
import { map } from 'rxjs/operators';
|
import { map, switchMap } from 'rxjs/operators';
|
||||||
import type { AuthOptions } from '../auth-options';
|
import type { AuthOptions } from '../auth-options';
|
||||||
import { AuthStateService } from '../auth-state/auth-state.service';
|
import { AuthStateService } from '../auth-state/auth-state.service';
|
||||||
import { ConfigurationService } from '../config/config.service';
|
import { ConfigurationService } from '../config/config.service';
|
||||||
@ -126,7 +126,7 @@ function checkAuth(
|
|||||||
configId?: string
|
configId?: string
|
||||||
): Observable<boolean> {
|
): Observable<boolean> {
|
||||||
return configurationService.getOpenIDConfiguration(configId).pipe(
|
return configurationService.getOpenIDConfiguration(configId).pipe(
|
||||||
map((configuration) => {
|
switchMap((configuration) => {
|
||||||
const isAuthenticated =
|
const isAuthenticated =
|
||||||
authStateService.areAuthStorageTokensValid(configuration);
|
authStateService.areAuthStorageTokensValid(configuration);
|
||||||
|
|
||||||
@ -137,13 +137,16 @@ function checkAuth(
|
|||||||
if (!isAuthenticated) {
|
if (!isAuthenticated) {
|
||||||
autoLoginService.saveRedirectRoute(configuration, url);
|
autoLoginService.saveRedirectRoute(configuration, url);
|
||||||
if (authOptions) {
|
if (authOptions) {
|
||||||
loginService.login(configuration, authOptions);
|
return loginService
|
||||||
} else {
|
.login(configuration, authOptions)
|
||||||
loginService.login(configuration);
|
.pipe(switchMap(() => of(isAuthenticated)));
|
||||||
}
|
}
|
||||||
|
return loginService
|
||||||
|
.login(configuration)
|
||||||
|
.pipe(switchMap(() => of(isAuthenticated)));
|
||||||
}
|
}
|
||||||
|
|
||||||
return isAuthenticated;
|
return of(isAuthenticated);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -40,6 +40,12 @@ export interface OpenIdConfiguration {
|
|||||||
* or if it contains additional audiences not trusted by the Client.
|
* or if it contains additional audiences not trusted by the Client.
|
||||||
*/
|
*/
|
||||||
clientId?: string;
|
clientId?: string;
|
||||||
|
/**
|
||||||
|
* @dangerous
|
||||||
|
* @see [client secret is missing](https://github.com/damienbod/angular-auth-oidc-client/issues/399)
|
||||||
|
* The client secret. For some oidc service the must provide this.
|
||||||
|
*/
|
||||||
|
clientSecret?: string;
|
||||||
/**
|
/**
|
||||||
* `code`, `id_token token` or `id_token`.
|
* `code`, `id_token token` or `id_token`.
|
||||||
* Name of the flow which can be configured.
|
* Name of the flow which can be configured.
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import { Injectable, inject } from '@outposts/injection-js';
|
import { Injectable, inject } from '@outposts/injection-js';
|
||||||
import { type Observable, of, throwError } from 'rxjs';
|
import { BehaviorSubject, type Observable, of, throwError } from 'rxjs';
|
||||||
|
import { MockUtil } from 'src/utils/reflect';
|
||||||
import type { AuthOptions } from '../auth-options';
|
import type { AuthOptions } from '../auth-options';
|
||||||
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
import type { OpenIdConfiguration } from '../config/openid-configuration';
|
||||||
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
import { StoragePersistenceService } from '../storage/storage-persistence.service';
|
||||||
@ -24,6 +25,7 @@ export class LoginService {
|
|||||||
|
|
||||||
private readonly popupService = inject(PopUpService);
|
private readonly popupService = inject(PopUpService);
|
||||||
|
|
||||||
|
@MockUtil({ implementation: () => new BehaviorSubject(undefined) })
|
||||||
login(
|
login(
|
||||||
configuration: OpenIdConfiguration | null,
|
configuration: OpenIdConfiguration | null,
|
||||||
authOptions?: AuthOptions
|
authOptions?: AuthOptions
|
||||||
|
@ -30,7 +30,7 @@ export abstract class AbstractRouter<
|
|||||||
abstract getCurrentNavigation(): NAVIGATION;
|
abstract getCurrentNavigation(): NAVIGATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class VanillaLocationRouter extends AbstractRouter {
|
export class VanillaLocationRouter extends AbstractRouter<string> {
|
||||||
protected document = inject(DOCUMENT);
|
protected document = inject(DOCUMENT);
|
||||||
|
|
||||||
private get location(): Location {
|
private get location(): Location {
|
||||||
|
@ -249,6 +249,7 @@ export class UrlService {
|
|||||||
configuration: OpenIdConfiguration
|
configuration: OpenIdConfiguration
|
||||||
): string | null {
|
): string | null {
|
||||||
const clientId = this.getClientId(configuration);
|
const clientId = this.getClientId(configuration);
|
||||||
|
const clientSecret = this.getClientSecret(configuration);
|
||||||
|
|
||||||
if (!clientId) {
|
if (!clientId) {
|
||||||
return null;
|
return null;
|
||||||
@ -259,6 +260,9 @@ export class UrlService {
|
|||||||
params = params.set('client_id', clientId);
|
params = params.set('client_id', clientId);
|
||||||
params = params.set('token', token);
|
params = params.set('token', token);
|
||||||
params = params.set('token_type_hint', 'access_token');
|
params = params.set('token_type_hint', 'access_token');
|
||||||
|
if (clientSecret) {
|
||||||
|
params = params.set('client_secret', clientSecret);
|
||||||
|
}
|
||||||
|
|
||||||
return params.toString();
|
return params.toString();
|
||||||
}
|
}
|
||||||
@ -268,6 +272,7 @@ export class UrlService {
|
|||||||
configuration: OpenIdConfiguration
|
configuration: OpenIdConfiguration
|
||||||
): string | null {
|
): string | null {
|
||||||
const clientId = this.getClientId(configuration);
|
const clientId = this.getClientId(configuration);
|
||||||
|
const clientSecret = this.getClientSecret(configuration);
|
||||||
|
|
||||||
if (!clientId) {
|
if (!clientId) {
|
||||||
return null;
|
return null;
|
||||||
@ -278,6 +283,9 @@ export class UrlService {
|
|||||||
params = params.set('client_id', clientId);
|
params = params.set('client_id', clientId);
|
||||||
params = params.set('token', token);
|
params = params.set('token', token);
|
||||||
params = params.set('token_type_hint', 'refresh_token');
|
params = params.set('token_type_hint', 'refresh_token');
|
||||||
|
if (clientSecret) {
|
||||||
|
params = params.set('client_secret', clientSecret);
|
||||||
|
}
|
||||||
|
|
||||||
return params.toString();
|
return params.toString();
|
||||||
}
|
}
|
||||||
@ -304,6 +312,7 @@ export class UrlService {
|
|||||||
customTokenParams?: { [p: string]: string | number | boolean }
|
customTokenParams?: { [p: string]: string | number | boolean }
|
||||||
): string | null {
|
): string | null {
|
||||||
const clientId = this.getClientId(configuration);
|
const clientId = this.getClientId(configuration);
|
||||||
|
const clientSecret = this.getClientSecret(configuration);
|
||||||
|
|
||||||
if (!clientId) {
|
if (!clientId) {
|
||||||
return null;
|
return null;
|
||||||
@ -313,6 +322,9 @@ export class UrlService {
|
|||||||
|
|
||||||
params = params.set('grant_type', 'authorization_code');
|
params = params.set('grant_type', 'authorization_code');
|
||||||
params = params.set('client_id', clientId);
|
params = params.set('client_id', clientId);
|
||||||
|
if (clientSecret) {
|
||||||
|
params = params.set('client_secret', clientSecret);
|
||||||
|
}
|
||||||
|
|
||||||
if (!configuration.disablePkce) {
|
if (!configuration.disablePkce) {
|
||||||
const codeVerifier = this.flowsDataService.getCodeVerifier(configuration);
|
const codeVerifier = this.flowsDataService.getCodeVerifier(configuration);
|
||||||
@ -364,6 +376,7 @@ export class UrlService {
|
|||||||
customParamsRefresh?: { [key: string]: string | number | boolean }
|
customParamsRefresh?: { [key: string]: string | number | boolean }
|
||||||
): string | null {
|
): string | null {
|
||||||
const clientId = this.getClientId(configuration);
|
const clientId = this.getClientId(configuration);
|
||||||
|
const clientSecret = this.getClientSecret(configuration);
|
||||||
|
|
||||||
if (!clientId) {
|
if (!clientId) {
|
||||||
return null;
|
return null;
|
||||||
@ -374,6 +387,9 @@ export class UrlService {
|
|||||||
params = params.set('grant_type', 'refresh_token');
|
params = params.set('grant_type', 'refresh_token');
|
||||||
params = params.set('client_id', clientId);
|
params = params.set('client_id', clientId);
|
||||||
params = params.set('refresh_token', refreshToken);
|
params = params.set('refresh_token', refreshToken);
|
||||||
|
if (clientSecret) {
|
||||||
|
params = params.set('client_secret', clientSecret);
|
||||||
|
}
|
||||||
|
|
||||||
if (customParamsRefresh) {
|
if (customParamsRefresh) {
|
||||||
params = this.appendCustomParams({ ...customParamsRefresh }, params);
|
params = this.appendCustomParams({ ...customParamsRefresh }, params);
|
||||||
@ -851,6 +867,18 @@ export class UrlService {
|
|||||||
return clientId;
|
return clientId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getClientSecret(configuration: OpenIdConfiguration): string | null {
|
||||||
|
const { clientSecret } = configuration;
|
||||||
|
|
||||||
|
if (!clientSecret) {
|
||||||
|
this.loggerService.logDebug(configuration, 'could not get clientSecret');
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return clientSecret;
|
||||||
|
}
|
||||||
|
|
||||||
private appendCustomParams(
|
private appendCustomParams(
|
||||||
customParams: { [key: string]: string | number | boolean },
|
customParams: { [key: string]: string | number | boolean },
|
||||||
params: HttpParams
|
params: HttpParams
|
||||||
|
Loading…
Reference in New Issue
Block a user