Skip to content

Commit

Permalink
Merge pull request #251 from movinsilva/feature/enhance-getauthorizat…
Browse files Browse the repository at this point in the history
…ionurl
  • Loading branch information
pavinduLakshan authored Apr 18, 2024
2 parents 6bb00d5 + fe0a465 commit c8f710a
Show file tree
Hide file tree
Showing 4 changed files with 139 additions and 27 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, which then can be used to build the authorization request.

#### Example

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

auth.getAuthorizationURLParams(config).then((params)=>{
console.log(params);
}).catch((error)=>{
console.error(error);
});
```

---

Expand Down
48 changes: 48 additions & 0 deletions lib/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,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"
}
72 changes: 46 additions & 26 deletions lib/src/core/authentication-core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,26 +62,17 @@ 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);

Expand All @@ -100,14 +91,21 @@ export class AuthenticationCore<T> {
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);
}
Expand All @@ -130,9 +128,31 @@ export class AuthenticationCore<T> {
STATE,
AuthenticationUtils.generateStateParamForRequestCorrelation(
pkceKey,
customParams ? customParams[ STATE ]?.toString() : ""
customParams ? customParams[STATE]?.toString() : ""
)
);

return authorizeRequestParams;
}

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);
Expand Down

0 comments on commit c8f710a

Please sign in to comment.