Skip to content

Commit

Permalink
feat: 🎨 extract and expose parameters building logic out of getAuthor…
Browse files Browse the repository at this point in the history
…izationURL function

can use the getAuthorizationURLParams() to build the authorize api call (usable for api based authentication)
  • Loading branch information
movinsilva committed Apr 17, 2024
1 parent 6bb00d5 commit 1521d4a
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 37 deletions.
43 changes: 43 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ If you are looking for an SDK to use in your application, then you can find the
- [constructor](#constructor)
- [initialize](#initialize)
- [getDataLayer](#getDataLayer)
- [getAuthorizationURLParams](#getAuthorizationURLParams)
- [getAuthorizationURL](#getAuthorizationURL)
- [requestAccessToken](#requestAccessToken)
- [getSignOutURL](#getSignOutURL)
Expand Down Expand Up @@ -323,6 +324,48 @@ This method returns the `CryptoHelper` object used by the SDK to perform cryptog
```TypeScript
const cryptoHelper = auth.getCryptoHelper();
```
---

### getAuthorizationURLParams

```TypeScript
getAuthorizationURLParams(config?: GetAuthURLConfig, userID?: string): Promise<Map<string, string>>
```

#### Arguments

1. config: [`GetAuthURLConfig`](#GetAuthURLConfig) (optional)

An optional config object that has the necessary attributes to configure this method. The `forceInit` attribute can be set to `true` to trigger a request to the `.well-known` endpoint and obtain the OIDC endpoints. By default, a request to the `.well-known` endpoint will be sent only if a request to it had not been sent before. If you wish to force a request to the endpoint, you can use this attribute.

The object can only contain key-value pairs that you wish to append as path parameters to the authorization URL. For example, to set the `fidp` parameter, you can insert `fidp` as a key and its value to this object.

2. userID: `string` (optional)

If you want to use the SDK to manage multiple user sessions, you can pass a unique ID here to generate an authorization URL specific to that user. This can be useful when this SDK is used in backend applications.

#### Returns

A Promise that resolves with the authorization URL Parameters.

#### Description

This method returns a Promise that resolves with the authorization URL Parameters. The user can use these parametres to build the authorization request.

#### Example

```TypeScript
const config = {
forceInit: true,
fidp: "fb"
}

auth.getAuthorizationURLParams(config).then((params)=>{

}).catch((error)=>{
console.error(error);
});
```

---

Expand Down
49 changes: 49 additions & 0 deletions lib/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,7 @@ export class AsgardeoAuthClient<T> {
cryptoUtils: CryptoUtils,
instanceID?: number
): Promise<void> {
console.log("Newest Local PACKAGE!!");
const clientId: string = config.clientID;

if (!AsgardeoAuthClient._instanceID) {
Expand Down Expand Up @@ -169,6 +170,54 @@ export class AsgardeoAuthClient<T> {
return AsgardeoAuthClient._instanceID;
}

/**
* This is an async method that returns a Promise that resolves with the authorization URL parameters.
*
* @param config - (Optional) A config object to force initialization and pass
* custom path parameters such as the fidp parameter.
* @param userID - (Optional) A unique ID of the user to be authenticated. This is useful in multi-user
* scenarios where each user should be uniquely identified.
*
* @returns - A promise that resolves with the authorization URL parameters.
*
* @example
* ```
* auth.getAuthorizationURLParams().then((params)=>{
* // console.log(params);
* }).catch((error)=>{
* // console.error(error);
* });
* ```
*
* {@link https://github.com/asgardeo/asgardeo-auth-js-sdk/tree/master#getAuthorizationURLParams}
*
* @preserve
*/
public async getAuthorizationURLParams(
config?: GetAuthURLConfig,
userID?: string
): Promise<Map<string, string>> {
const authRequestConfig: GetAuthURLConfig = { ...config };

delete authRequestConfig?.forceInit;

if (await this._dataLayer.getTemporaryDataParameter(OP_CONFIG_INITIATED)) {
return this._authenticationCore.getAuthorizationURLParams(
authRequestConfig,
userID
);
}

return this._authenticationCore
.getOIDCProviderMetaData(config?.forceInit as boolean)
.then(() => {
return this._authenticationCore.getAuthorizationURLParams(
authRequestConfig,
userID
);
});
}

/**
* This is an async method that returns a Promise that resolves with the authorization URL.
*
Expand Down
3 changes: 2 additions & 1 deletion lib/src/constants/client-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,5 +18,6 @@

export enum ResponseMode {
formPost = "form_post",
query = "query"
query = "query",
direct = "direct"
}
92 changes: 56 additions & 36 deletions lib/src/core/authentication-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,82 +62,102 @@ export class AuthenticationCore<T> {
this._oidcProviderMetaData = async () => await this._dataLayer.getOIDCProviderMetaData();
}

public async getAuthorizationURL(config?: AuthorizationURLParams, userID?: string): Promise<string> {
const authorizeEndpoint: string = (await this._dataLayer.getOIDCProviderMetaDataParameter(
AUTHORIZATION_ENDPOINT as keyof OIDCProviderMetaData
)) as string;

public async getAuthorizationURLParams(
config?: AuthorizationURLParams,
userID?: string
): Promise<Map<string, string>> {
const configData: StrictAuthClientConfig = await this._config();

if (!authorizeEndpoint || authorizeEndpoint.trim().length === 0) {
throw new AsgardeoAuthException(
"JS-AUTH_CORE-GAU-NF01",
"No authorization endpoint found.",
"No authorization endpoint was found in the OIDC provider meta data from the well-known endpoint " +
"or the authorization endpoint passed to the SDK is empty."
);
}

const authorizeRequest: URL = new URL(authorizeEndpoint);

const authorizeRequestParams: Map<string, string> = new Map<string, string>();


const authorizeRequestParams: Map<string, string> = new Map<
string,
string
>();

authorizeRequestParams.set("response_type", "code");
authorizeRequestParams.set("client_id", configData.clientID);

let scope: string = OIDC_SCOPE;

if (configData.scope && configData.scope.length > 0) {
if (!configData.scope.includes(OIDC_SCOPE)) {
configData.scope.push(OIDC_SCOPE);
}
scope = configData.scope.join(" ");
}

authorizeRequestParams.set("scope", scope);
authorizeRequestParams.set("redirect_uri", configData.signInRedirectURL);

if (configData.responseMode) {
authorizeRequestParams.set("response_mode", configData.responseMode);
}

const pkceKey: string = await this._authenticationHelper.generatePKCEKey(userID);


const pkceKey: string = await this._authenticationHelper.generatePKCEKey(
userID
);

if (configData.enablePKCE) {
const codeVerifier: string = this._cryptoHelper?.getCodeVerifier();
const codeChallenge: string = this._cryptoHelper?.getCodeChallenge(codeVerifier);

await this._dataLayer.setTemporaryDataParameter(pkceKey, codeVerifier, userID);
const codeChallenge: string =
this._cryptoHelper?.getCodeChallenge(codeVerifier);

await this._dataLayer.setTemporaryDataParameter(
pkceKey,
codeVerifier,
userID
);
authorizeRequestParams.set("code_challenge_method", "S256");
authorizeRequestParams.set("code_challenge", codeChallenge);
}

if (configData.prompt) {
authorizeRequestParams.set("prompt", configData.prompt);
}

const customParams: AuthorizationURLParams | undefined = config;

if (customParams) {
for (const [ key, value ] of Object.entries(customParams)) {
if (key != "" && value != "" && key !== STATE) {
authorizeRequestParams.set(key, value.toString());
}
}
}

authorizeRequestParams.set(
STATE,
AuthenticationUtils.generateStateParamForRequestCorrelation(
pkceKey,
customParams ? customParams[ STATE ]?.toString() : ""
customParams ? customParams[STATE]?.toString() : ""
)
);

return authorizeRequestParams;
}

for (const [ key, value ] of authorizeRequestParams.entries()) {
authorizeRequest.searchParams.append(key, value);
public async getAuthorizationURL(config?: AuthorizationURLParams, userID?: string): Promise<string> {
const authorizeEndpoint: string = (await this._dataLayer.getOIDCProviderMetaDataParameter(
AUTHORIZATION_ENDPOINT as keyof OIDCProviderMetaData
)) as string;

if (!authorizeEndpoint || authorizeEndpoint.trim().length === 0) {
throw new AsgardeoAuthException(
"JS-AUTH_CORE-GAU-NF01",
"No authorization endpoint found.",
"No authorization endpoint was found in the OIDC provider meta data from the well-known endpoint " +
"or the authorization endpoint passed to the SDK is empty."
);
}

const authorizeRequest: URL = new URL(authorizeEndpoint);

const authorizeRequestParams: Map<string, string> =
await this.getAuthorizationURLParams(config, userID);

for (const [ key, value ] of authorizeRequestParams.entries()) {
authorizeRequest.searchParams.append(key, value);
}

return authorizeRequest.toString();
}

Expand Down

0 comments on commit 1521d4a

Please sign in to comment.