Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enhance getAuthorizationURL function #251

Merged
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>>
pavinduLakshan marked this conversation as resolved.
Show resolved Hide resolved
```

#### 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.
movinsilva marked this conversation as resolved.
Show resolved Hide resolved

#### Example

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

auth.getAuthorizationURLParams(config).then((params)=>{
console.log(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!!");
pavinduLakshan marked this conversation as resolved.
Show resolved Hide resolved
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.
pavinduLakshan marked this conversation as resolved.
Show resolved Hide resolved
* @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
pavinduLakshan marked this conversation as resolved.
Show resolved Hide resolved
*/
public async getAuthorizationURLParams(
config?: GetAuthURLConfig,
userID?: string
): Promise<Map<string, string>> {
const authRequestConfig: GetAuthURLConfig = { ...config };

delete authRequestConfig?.forceInit;
pavinduLakshan marked this conversation as resolved.
Show resolved Hide resolved

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

movinsilva marked this conversation as resolved.
Show resolved Hide resolved
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