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

feat: provide method to set request headers #891

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all 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
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## 5.3.0


### Features

- [#891](https://github.com/okta/okta-auth-js/pull/891) Adds new method `http.setRequestHeader`

### Bug Fixes

- [#852](https://github.com/okta/okta-auth-js/pull/852) Skips non-successful requests cacheing
Expand Down
10 changes: 10 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -866,6 +866,8 @@ Defaults to `none` if the `secure` option is `true`, or `lax` if the `secure` op
* [authStateManager.updateAuthState](#authstatemanagerupdateauthstate)
* [authStateManager.subscribe](#authstatemanagersubscribehandler)
* [authStateManager.unsubscribe](#authstatemanagerunsubscribehandler)
* [http](#http)
* [http.setRequestHeader](#httpsetrequestheader)

------

Expand Down Expand Up @@ -2645,6 +2647,14 @@ var config = {
var authClient = new OktaAuth(config);
```

### `http`

The `http` API allows customization of network requests made by internal HTTP agents.

#### `http.setRequestHeader`

Sets the value for a request header after [configuration options](#configuration-options) have already been processed. Headers can also be customized by setting a `headers` object in the [configuration](#configuration-options) object.

### Supported APIs

Since the Node library can be used only for the Authentication flow, it implements only a subset of okta-auth-js APIs:
Expand Down
13 changes: 11 additions & 2 deletions lib/OktaAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import {
SigninOptions,
IdxAPI,
SignoutRedirectUrlOptions,
HttpAPI,
} from './types';
import {
transactionStatus,
Expand Down Expand Up @@ -88,7 +89,7 @@ import {
clone
} from './util';
import { TokenManager } from './TokenManager';
import http from './http';
import { get, setRequestHeader } from './http';
import PromiseQueue from './PromiseQueue';
import fingerprint from './browser/fingerprint';
import { AuthStateManager } from './AuthStateManager';
Expand All @@ -103,6 +104,7 @@ import {
startTransaction,
handleInteractionCodeRedirect,
} from './idx';
import { createGlobalRequestInterceptor, setGlobalRequestInterceptor } from './idx/headers';
import { OktaUserAgent } from './OktaUserAgent';

const Emitter = require('tiny-emitter');
Expand All @@ -122,6 +124,7 @@ class OktaAuth implements SDKInterface, SigninAPI, SignoutAPI {
emitter: typeof Emitter;
tokenManager: TokenManager;
authStateManager: AuthStateManager;
http: HttpAPI;
fingerprint: FingerprintAPI;
_oktaUserAgent: OktaUserAgent;
_pending: { handleLogin: boolean };
Expand Down Expand Up @@ -246,6 +249,12 @@ class OktaAuth implements SDKInterface, SigninAPI, SignoutAPI {
handleInteractionCodeRedirect: handleInteractionCodeRedirect.bind(null, this),
startTransaction: startTransaction.bind(null, this),
};
setGlobalRequestInterceptor(createGlobalRequestInterceptor(this)); // to pass custom headers to IDX endpoints

// HTTP
this.http = {
setRequestHeader: setRequestHeader.bind(null, this)
};

// Fingerprint API
this.fingerprint = fingerprint.bind(null, this);
Expand Down Expand Up @@ -465,7 +474,7 @@ class OktaAuth implements SDKInterface, SigninAPI, SignoutAPI {
'Accept': 'application/jrd+json'
}
};
return http.get(this, url, options);
return get(this, url, options);
}

//
Expand Down
13 changes: 13 additions & 0 deletions lib/OktaUserAgent.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
/*!
* Copyright (c) 2015-present, Okta, Inc. and/or its affiliates. All rights reserved.
* The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
*
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and limitations under the License.
*
*/

/* global SDK_VERSION */
import { isBrowser } from './features';

Expand Down
18 changes: 18 additions & 0 deletions lib/http/headers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/*!
* Copyright (c) 2015-present, Okta, Inc. and/or its affiliates. All rights reserved.
* The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
*
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and limitations under the License.
*
*/
import { OktaAuth } from '../types';

export function setRequestHeader(authClient: OktaAuth, headerName, headerValue) {
authClient.options.headers = authClient.options.headers || {};
authClient.options.headers[headerName] = headerValue;
}
2 changes: 2 additions & 0 deletions lib/http/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './headers';
export * from './request';
20 changes: 7 additions & 13 deletions lib/http.ts → lib/http/request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@
*/

/* eslint-disable complexity */
import { isString, clone, isAbsoluteUrl, removeNils } from './util';
import AuthApiError from './errors/AuthApiError';
import { STATE_TOKEN_KEY_NAME, DEFAULT_CACHE_DURATION } from './constants';
import { OktaAuth, RequestOptions, FetchOptions, RequestData } from './types';
import { isString, clone, isAbsoluteUrl, removeNils } from '../util';
import AuthApiError from '../errors/AuthApiError';
import { STATE_TOKEN_KEY_NAME, DEFAULT_CACHE_DURATION } from '../constants';
import { OktaAuth, RequestOptions, FetchOptions, RequestData } from '../types';

function httpRequest(sdk: OktaAuth, options: RequestOptions): Promise<any> {
export function httpRequest(sdk: OktaAuth, options: RequestOptions): Promise<any> {
options = options || {};
var url = options.url,
method = options.method,
Expand Down Expand Up @@ -113,7 +113,7 @@ function httpRequest(sdk: OktaAuth, options: RequestOptions): Promise<any> {
});
}

function get(sdk: OktaAuth, url: string, options?: RequestOptions) {
export function get(sdk: OktaAuth, url: string, options?: RequestOptions) {
url = isAbsoluteUrl(url) ? url : sdk.getIssuerOrigin() + url;
var getOptions = {
url: url,
Expand All @@ -123,7 +123,7 @@ function get(sdk: OktaAuth, url: string, options?: RequestOptions) {
return httpRequest(sdk, getOptions);
}

function post(sdk: OktaAuth, url: string, args?: RequestData, options?: RequestOptions) {
export function post(sdk: OktaAuth, url: string, args?: RequestData, options?: RequestOptions) {
url = isAbsoluteUrl(url) ? url : sdk.getIssuerOrigin() + url;
var postOptions = {
url: url,
Expand All @@ -134,9 +134,3 @@ function post(sdk: OktaAuth, url: string, args?: RequestData, options?: RequestO
Object.assign(postOptions, options);
return httpRequest(sdk, postOptions);
}

export default {
get: get,
post: post,
httpRequest: httpRequest
};
36 changes: 36 additions & 0 deletions lib/idx/headers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
/*!
* Copyright (c) 2015-present, Okta, Inc. and/or its affiliates. All rights reserved.
* The Okta software accompanied by this notice is provided pursuant to the Apache License, Version 2.0 (the "License.")
*
* You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
* See the License for the specific language governing permissions and limitations under the License.
*
*/

// BETA - SUBJECT TO CHANGE
// Currently we must modify request headers using the single instance of `idx.client.interceptors` exported from IDX-JS
// This means that multiple instances of OktaAuth will see the same header modifications
// TODO: use AuthJS http agent for IDX API requests. OKTA-417473
import { OktaAuth } from '../types';
import idx from '@okta/okta-idx-js';
export function setGlobalRequestInterceptor(fn) {
idx.client.interceptors.request.use(fn);
}

// A factory which returns a function that can be passed to `setGlobalRequestInterceptor`
export function createGlobalRequestInterceptor(sdk: OktaAuth) {
return function (requestConfig) {
// Set user-agent and any other custom headers set in the options
var oktaUserAgentHeader = sdk._oktaUserAgent.getHttpHeader();
const headers = Object.assign({
...oktaUserAgentHeader
}, sdk.options.headers);
Object.keys(headers).forEach(name => {
requestConfig.headers[name] = headers[name];
});
};
}
6 changes: 3 additions & 3 deletions lib/oidc/endpoints/token.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import { AuthSdkError } from '../../errors';
import { CustomUrls, OAuthParams, OAuthResponse, RefreshToken, TokenParams } from '../../types';
import { removeNils, toQueryString } from '../../util';
import http from '../../http';
import { httpRequest } from '../../http';

function validateOptions(options: TokenParams) {
// Quick validation
Expand Down Expand Up @@ -68,7 +68,7 @@ export function postToTokenEndpoint(sdk, options: TokenParams, urls: CustomUrls)
'Content-Type': 'application/x-www-form-urlencoded'
};

return http.httpRequest(sdk, {
return httpRequest(sdk, {
url: urls.tokenUrl,
method: 'POST',
args: data,
Expand All @@ -77,7 +77,7 @@ export function postToTokenEndpoint(sdk, options: TokenParams, urls: CustomUrls)
}

export function postRefreshToken(sdk, options: TokenParams, refreshToken: RefreshToken): Promise<OAuthResponse> {
return http.httpRequest(sdk, {
return httpRequest(sdk, {
url: refreshToken.tokenUrl,
method: 'POST',
headers: {
Expand Down
6 changes: 3 additions & 3 deletions lib/oidc/endpoints/well-known.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,14 @@
* See the License for the specific language governing permissions and limitations under the License.
*
*/
import http from '../../http';
import { get } from '../../http';
import { find } from '../../util';
import { OktaAuth, WellKnownResponse } from '../../types';
import AuthSdkError from '../../errors/AuthSdkError';

export function getWellKnown(sdk: OktaAuth, issuer?: string): Promise<WellKnownResponse> {
var authServerUri = (issuer || sdk.options.issuer);
return http.get(sdk, authServerUri + '/.well-known/openid-configuration', {
return get(sdk, authServerUri + '/.well-known/openid-configuration', {
cacheResponse: true
});
}
Expand Down Expand Up @@ -46,7 +46,7 @@ export function getKey(sdk: OktaAuth, issuer: string, kid: string): Promise<stri
httpCache.clearStorage(jwksUri);

// Pull the latest keys if the key wasn't in the cache
return http.get(sdk, jwksUri, {
return get(sdk, jwksUri, {
cacheResponse: true
})
.then(function(res) {
Expand Down
4 changes: 2 additions & 2 deletions lib/oidc/getUserInfo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
*/
import { isFunction } from '../util';
import { AuthSdkError, OAuthError } from '../errors';
import http from '../http';
import { httpRequest } from '../http';
import { AccessToken, IDToken, UserClaims, isAccessToken, isIDToken } from '../types';

export async function getUserInfo(sdk, accessTokenObject: AccessToken, idTokenObject: IDToken): Promise<UserClaims> {
Expand All @@ -33,7 +33,7 @@ export async function getUserInfo(sdk, accessTokenObject: AccessToken, idTokenOb
return Promise.reject(new AuthSdkError('getUserInfo requires an ID token object'));
}

return http.httpRequest(sdk, {
return httpRequest(sdk, {
url: accessTokenObject.userinfoUrl,
method: 'GET',
accessToken: accessTokenObject.accessToken
Expand Down
4 changes: 2 additions & 2 deletions lib/oidc/revokeToken.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
*/

/* eslint complexity:[0,8] */
import http from '../http';
import { post } from '../http';
import { toQueryString } from '../util';
import {
getOAuthUrls,
Expand Down Expand Up @@ -52,7 +52,7 @@ export function revokeToken(sdk: OktaAuth, token: RevocableToken): Promise<any>
token: refreshToken || accessToken,
}).slice(1);
var creds = clientSecret ? btoa(`${clientId}:${clientSecret}`) : btoa(clientId);
return http.post(sdk, revokeUrl, args, {
return post(sdk, revokeUrl, args, {
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + creds
Expand Down
12 changes: 6 additions & 6 deletions lib/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
*/
/* global window */
import { omit, getLink, toQueryString } from './util';
import http from './http';
import { get, post, httpRequest } from './http';

function sessionExists(sdk) {
return sdk.session.get()
Expand All @@ -28,16 +28,16 @@ function sessionExists(sdk) {
}

function getSession(sdk) {
return http.get(sdk, '/api/v1/sessions/me', { withCredentials: true })
return get(sdk, '/api/v1/sessions/me', { withCredentials: true })
.then(function(session) {
var res = omit(session, '_links');

res.refresh = function() {
return http.post(sdk, getLink(session, 'refresh').href, {}, { withCredentials: true });
return post(sdk, getLink(session, 'refresh').href, {}, { withCredentials: true });
};

res.user = function() {
return http.get(sdk, getLink(session, 'user').href, { withCredentials: true });
return get(sdk, getLink(session, 'user').href, { withCredentials: true });
};

return res;
Expand All @@ -49,15 +49,15 @@ function getSession(sdk) {
}

function closeSession(sdk) {
return http.httpRequest(sdk, {
return httpRequest(sdk, {
url: sdk.getIssuerOrigin() + '/api/v1/sessions/me',
method: 'DELETE',
withCredentials: true
});
}

function refreshSession(sdk) {
return http.post(sdk, '/api/v1/sessions/me/lifecycle/refresh', {}, { withCredentials: true });
return post(sdk, '/api/v1/sessions/me/lifecycle/refresh', {}, { withCredentials: true });
}

function setCookieAndRedirect(sdk, sessionToken, redirectUrl) {
Expand Down
4 changes: 2 additions & 2 deletions lib/tx/AuthTransaction.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
*
*/

import http from '../http';
import { get } from '../http';
import { find, omit, toQueryString, clone, isObject } from '../util';
import AuthSdkError from '../errors/AuthSdkError';
import { TransactionState } from './TransactionState';
Expand Down Expand Up @@ -125,7 +125,7 @@ function link2fn(sdk, res, obj, link, ref) {

case 'GET':
return function() {
return http.get(sdk, link.href, { withCredentials: true });
return get(sdk, link.href, { withCredentials: true });
};

case 'POST':
Expand Down
Loading