mirror of
https://github.com/Kong/insomnia.git
synced 2026-04-20 22:27:24 -04:00
oAuth 1.0a Support (#571)
This commit is contained in:
committed by
Gregory Schier
parent
c0f4849697
commit
d3e8a05fc7
@@ -1,10 +1,11 @@
|
||||
// @flow
|
||||
import type {BaseModel} from './index';
|
||||
import {AUTH_BASIC, AUTH_DIGEST, AUTH_NONE, AUTH_NTLM, AUTH_OAUTH_2, AUTH_HAWK, AUTH_AWS_IAM, AUTH_NETRC, CONTENT_TYPE_FILE, CONTENT_TYPE_FORM_DATA, CONTENT_TYPE_FORM_URLENCODED, CONTENT_TYPE_OTHER, getContentTypeFromHeaders, METHOD_GET, CONTENT_TYPE_GRAPHQL, CONTENT_TYPE_JSON, METHOD_POST, HAWK_ALGORITHM_SHA256} from '../common/constants';
|
||||
import {AUTH_BASIC, AUTH_DIGEST, AUTH_NONE, AUTH_NTLM, AUTH_OAUTH_1, AUTH_OAUTH_2, AUTH_HAWK, AUTH_AWS_IAM, AUTH_NETRC, CONTENT_TYPE_FILE, CONTENT_TYPE_FORM_DATA, CONTENT_TYPE_FORM_URLENCODED, CONTENT_TYPE_OTHER, getContentTypeFromHeaders, METHOD_GET, CONTENT_TYPE_GRAPHQL, CONTENT_TYPE_JSON, METHOD_POST, HAWK_ALGORITHM_SHA256} from '../common/constants';
|
||||
import * as db from '../common/database';
|
||||
import {getContentTypeHeader} from '../common/misc';
|
||||
import {buildFromParams, deconstructToParams} from '../common/querystring';
|
||||
import {GRANT_TYPE_AUTHORIZATION_CODE} from '../network/o-auth-2/constants';
|
||||
import {SIGNATURE_METHOD_HMAC_SHA1} from '../network/o-auth-1/constants';
|
||||
|
||||
export const name = 'Request';
|
||||
export const type = 'Request';
|
||||
@@ -99,6 +100,14 @@ export function newAuth (type: string, oldAuth: RequestAuthentication = {}): Req
|
||||
password: oldAuth.password || ''
|
||||
};
|
||||
|
||||
case AUTH_OAUTH_1:
|
||||
return {
|
||||
type,
|
||||
disabled: false,
|
||||
signatureMethod: SIGNATURE_METHOD_HMAC_SHA1,
|
||||
version: '1.0'
|
||||
};
|
||||
|
||||
// OAuth 2.0
|
||||
case AUTH_OAUTH_2:
|
||||
return {type, grantType: GRANT_TYPE_AUTHORIZATION_CODE};
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {AUTH_BASIC, AUTH_BEARER, AUTH_OAUTH_2, AUTH_HAWK} from '../common/constants';
|
||||
import {AUTH_BASIC, AUTH_BEARER, AUTH_OAUTH_2, AUTH_OAUTH_1, AUTH_HAWK} from '../common/constants';
|
||||
import {getBasicAuthHeader, getBearerAuthHeader} from '../common/misc';
|
||||
import getOAuth2Token from './o-auth-2/get-token';
|
||||
import getOAuth1Token from './o-auth-1/get-token';
|
||||
import * as Hawk from 'hawk';
|
||||
|
||||
export async function getAuthHeader (requestId, url, method, authentication) {
|
||||
@@ -28,6 +29,18 @@ export async function getAuthHeader (requestId, url, method, authentication) {
|
||||
}
|
||||
}
|
||||
|
||||
if (authentication.type === AUTH_OAUTH_1) {
|
||||
const oAuth1Token = await getOAuth1Token(url, method, authentication);
|
||||
if (oAuth1Token) {
|
||||
return {
|
||||
name: 'Authorization',
|
||||
value: oAuth1Token.Authorization
|
||||
};
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
if (authentication.type === AUTH_HAWK) {
|
||||
const {id, key, algorithm} = authentication;
|
||||
|
||||
|
||||
2
app/network/o-auth-1/constants.js
Normal file
2
app/network/o-auth-1/constants.js
Normal file
@@ -0,0 +1,2 @@
|
||||
export const SIGNATURE_METHOD_HMAC_SHA1 = 'HMAC-SHA1';
|
||||
export const SIGNATURE_METHOD_PLAINTEXT = 'PLAINTEXT';
|
||||
42
app/network/o-auth-1/get-token.js
Normal file
42
app/network/o-auth-1/get-token.js
Normal file
@@ -0,0 +1,42 @@
|
||||
/**
|
||||
* Get an OAuth1Token object and also handle storing/saving/refreshing
|
||||
* @returns {Promise.<void>}
|
||||
*/
|
||||
import crypto from 'crypto';
|
||||
import OAuth1 from 'oauth-1.0a';
|
||||
import { SIGNATURE_METHOD_HMAC_SHA1, SIGNATURE_METHOD_PLAINTEXT } from './constants';
|
||||
|
||||
function hashFunction (signatureMethod) {
|
||||
if (signatureMethod === SIGNATURE_METHOD_HMAC_SHA1) {
|
||||
return function (baseString, key) {
|
||||
return crypto.createHmac('sha1', key).update(baseString).digest('base64');
|
||||
};
|
||||
}
|
||||
|
||||
if (signatureMethod === SIGNATURE_METHOD_PLAINTEXT) {
|
||||
return function (baseString) {
|
||||
return baseString;
|
||||
};
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
export default async function (url, method, authentication) {
|
||||
var oauth = OAuth1({
|
||||
consumer: {
|
||||
key: authentication.consumerKey,
|
||||
secret: authentication.consumerSecret
|
||||
},
|
||||
signature_method: authentication.signatureMethod,
|
||||
version: authentication.version,
|
||||
hash_function: hashFunction(authentication.signatureMethod)
|
||||
});
|
||||
|
||||
var requestData = {
|
||||
url: url,
|
||||
method: method
|
||||
};
|
||||
|
||||
return oauth.toHeader(oauth.authorize(requestData));
|
||||
}
|
||||
@@ -6,11 +6,11 @@ import DigestAuth from './digest-auth';
|
||||
import BearerAuth from './bearer-auth';
|
||||
import NTLMAuth from './ntlm-auth';
|
||||
import OAuth2Auth from './o-auth-2-auth';
|
||||
import OAuth1Auth from './o-auth-1-auth';
|
||||
import HawkAuth from './hawk-auth';
|
||||
import AWSAuth from './aws-auth';
|
||||
import NetrcAuth from './netrc-auth';
|
||||
import autobind from 'autobind-decorator';
|
||||
import Link from '../../base/link';
|
||||
|
||||
@autobind
|
||||
class AuthWrapper extends PureComponent {
|
||||
@@ -65,17 +65,13 @@ class AuthWrapper extends PureComponent {
|
||||
);
|
||||
} else if (authentication.type === AUTH_OAUTH_1) {
|
||||
return (
|
||||
<div className="vertically-center text-center">
|
||||
<div className="pad text-sm text-center">
|
||||
<i className="fa fa-commenting super-faint" style={{fontSize: '8rem', opacity: 0.3}}/>
|
||||
<p className="faint pad-top">
|
||||
Want OAuth 1.0? Please upvote
|
||||
the <Link href="https://github.com/getinsomnia/insomnia/issues/197">
|
||||
Issue on GitHub
|
||||
</Link>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<OAuth1Auth
|
||||
request={request}
|
||||
handleRender={handleRender}
|
||||
handleGetRenderContext={handleGetRenderContext}
|
||||
nunjucksPowerUserMode={nunjucksPowerUserMode}
|
||||
onChange={onChange}
|
||||
/>
|
||||
);
|
||||
} else if (authentication.type === AUTH_DIGEST) {
|
||||
return (
|
||||
|
||||
173
app/ui/components/editors/auth/o-auth-1-auth.js
Normal file
173
app/ui/components/editors/auth/o-auth-1-auth.js
Normal file
@@ -0,0 +1,173 @@
|
||||
// @flow
|
||||
import type {Request} from '../../../../models/request';
|
||||
|
||||
import * as React from 'react';
|
||||
import autobind from 'autobind-decorator';
|
||||
import OneLineEditor from '../../codemirror/one-line-editor';
|
||||
import * as misc from '../../../../common/misc';
|
||||
import HelpTooltip from '../../help-tooltip';
|
||||
import { SIGNATURE_METHOD_HMAC_SHA1, SIGNATURE_METHOD_PLAINTEXT } from '../../../../network/o-auth-1/constants';
|
||||
|
||||
type Props = {
|
||||
handleRender: Function,
|
||||
handleGetRenderContext: Function,
|
||||
nunjucksPowerUserMode: boolean,
|
||||
onChange: Function,
|
||||
request: Request
|
||||
};
|
||||
|
||||
@autobind
|
||||
class OAuth1Auth extends React.PureComponent<Props> {
|
||||
_handleChangeProperty: Function;
|
||||
|
||||
constructor (props: any) {
|
||||
super(props);
|
||||
|
||||
this._handleChangeProperty = misc.debounce(this._handleChangeProperty, 500);
|
||||
}
|
||||
|
||||
_handleChangeProperty (property: string, value: string | boolean): void {
|
||||
const {request} = this.props;
|
||||
const authentication = Object.assign({}, request.authentication, {[property]: value});
|
||||
this.props.onChange(authentication);
|
||||
}
|
||||
|
||||
_handleChangeConsumerKey (value: string): void {
|
||||
this._handleChangeProperty('consumerKey', value);
|
||||
}
|
||||
|
||||
_handleChangeConsumerSecret (value: string): void {
|
||||
this._handleChangeProperty('consumerSecret', value);
|
||||
}
|
||||
|
||||
_handleChangeSignatureMethod (e: SyntheticEvent<HTMLInputElement>): void {
|
||||
this._handleChangeProperty('signatureMethod', e.currentTarget.value);
|
||||
}
|
||||
|
||||
_handleChangeVersion (value: string): void {
|
||||
this._handleChangeProperty('version', value);
|
||||
}
|
||||
|
||||
renderInputRow (
|
||||
label: string,
|
||||
property: string,
|
||||
onChange: Function,
|
||||
help: string | null = null,
|
||||
handleAutocomplete: Function | null = null
|
||||
): React.Element<*> {
|
||||
const {handleRender, handleGetRenderContext, request, nunjucksPowerUserMode} = this.props;
|
||||
const id = label.replace(/ /g, '-');
|
||||
const type = !this.props.showPasswords && property === 'password' ? 'password' : 'text';
|
||||
return (
|
||||
<tr key={id}>
|
||||
<td className="pad-right no-wrap valign-middle">
|
||||
<label htmlFor={id} className="label--small no-pad">
|
||||
{label}
|
||||
{help && <HelpTooltip>{help}</HelpTooltip>}
|
||||
</label>
|
||||
</td>
|
||||
<td className="wide">
|
||||
<div className="form-control form-control--underlined no-margin">
|
||||
<OneLineEditor
|
||||
id={id}
|
||||
type={type}
|
||||
onChange={onChange}
|
||||
defaultValue={request.authentication[property] || ''}
|
||||
render={handleRender}
|
||||
nunjucksPowerUserMode={nunjucksPowerUserMode}
|
||||
getAutocompleteConstants={handleAutocomplete}
|
||||
getRenderContext={handleGetRenderContext}
|
||||
/>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
|
||||
renderSelectRow (
|
||||
label: string,
|
||||
property: string,
|
||||
options: Array<{name: string, value: string}>,
|
||||
onChange: Function,
|
||||
help: string | null = null
|
||||
): React.Element<*> {
|
||||
const {request} = this.props;
|
||||
const id = label.replace(/ /g, '-');
|
||||
const value = request.authentication.hasOwnProperty(property)
|
||||
? request.authentication[property]
|
||||
: options[0];
|
||||
|
||||
return (
|
||||
<tr key={id}>
|
||||
<td className="pad-right no-wrap valign-middle">
|
||||
<label htmlFor={id} className="label--small no-pad">
|
||||
{label}
|
||||
{help && <HelpTooltip>{help}</HelpTooltip>}
|
||||
</label>
|
||||
</td>
|
||||
<td className="wide">
|
||||
<div className="form-control form-control--outlined no-margin">
|
||||
<select id={id} onChange={onChange} value={value}>
|
||||
{options.map(({name, value}) => (
|
||||
<option key={value} value={value}>{name}</option>
|
||||
))}
|
||||
</select>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
);
|
||||
}
|
||||
|
||||
renderFields (): Array<React.Element<*>> {
|
||||
const consumerKey = this.renderInputRow(
|
||||
'Consumer Key',
|
||||
'consumerKey',
|
||||
this._handleChangeConsumerKey
|
||||
);
|
||||
|
||||
const consumerSecret = this.renderInputRow(
|
||||
'Consumer Secret',
|
||||
'consumerSecret',
|
||||
this._handleChangeConsumerSecret
|
||||
);
|
||||
|
||||
const signatureMethod = this.renderSelectRow(
|
||||
'Signature Method',
|
||||
'signatureMethod',
|
||||
[
|
||||
{name: 'HMAC-SHA1', value: SIGNATURE_METHOD_HMAC_SHA1},
|
||||
{name: 'PLAINTEXT', value: SIGNATURE_METHOD_PLAINTEXT}
|
||||
],
|
||||
this._handleChangeSignatureMethod
|
||||
);
|
||||
|
||||
const version = this.renderInputRow(
|
||||
'Version',
|
||||
'version',
|
||||
this._handleChangeVersion
|
||||
);
|
||||
|
||||
return [
|
||||
consumerKey,
|
||||
consumerSecret,
|
||||
signatureMethod,
|
||||
version
|
||||
];
|
||||
}
|
||||
|
||||
render () {
|
||||
const fields = this.renderFields();
|
||||
|
||||
return (
|
||||
<div className="pad">
|
||||
<table>
|
||||
<tbody>
|
||||
{fields}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default OAuth1Auth;
|
||||
65
package-lock.json
generated
65
package-lock.json
generated
@@ -4,12 +4,6 @@
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@types/node": {
|
||||
"version": "7.0.46",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.46.tgz",
|
||||
"integrity": "sha512-u+JAi1KtmaUoU/EHJkxoiuvzyo91FCE41Z9TZWWcOUU3P8oUdlDLdrGzCGWySPgbRMD17B0B+1aaJLYI9egQ6A==",
|
||||
"dev": true
|
||||
},
|
||||
"7zip": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/7zip/-/7zip-0.0.6.tgz",
|
||||
@@ -31,6 +25,22 @@
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@types/node": {
|
||||
"version": "7.0.46",
|
||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-7.0.46.tgz",
|
||||
"integrity": "sha512-u+JAi1KtmaUoU/EHJkxoiuvzyo91FCE41Z9TZWWcOUU3P8oUdlDLdrGzCGWySPgbRMD17B0B+1aaJLYI9egQ6A==",
|
||||
"dev": true
|
||||
},
|
||||
"JSONSelect": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/JSONSelect/-/JSONSelect-0.4.0.tgz",
|
||||
"integrity": "sha1-oI7cxn6z/L6Z7WMIVTRKDPKCu40="
|
||||
},
|
||||
"JSV": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/JSV/-/JSV-4.0.2.tgz",
|
||||
"integrity": "sha1-0Hf2glVx+CEy+d/67Vh7QCn+/1c="
|
||||
},
|
||||
"a-sync-waterfall": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/a-sync-waterfall/-/a-sync-waterfall-1.0.0.tgz",
|
||||
@@ -5113,10 +5123,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"bundled": true
|
||||
},
|
||||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
@@ -5126,6 +5132,10 @@
|
||||
"strip-ansi": "3.0.1"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"bundled": true
|
||||
},
|
||||
"stringstream": {
|
||||
"version": "0.0.5",
|
||||
"bundled": true,
|
||||
@@ -6697,10 +6707,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"bundled": true
|
||||
},
|
||||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
@@ -6710,6 +6716,10 @@
|
||||
"strip-ansi": "3.0.1"
|
||||
}
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"bundled": true
|
||||
},
|
||||
"stringstream": {
|
||||
"version": "0.0.5",
|
||||
"bundled": true
|
||||
@@ -7590,12 +7600,12 @@
|
||||
"resolved": "https://registry.npmjs.org/jison/-/jison-0.4.13.tgz",
|
||||
"integrity": "sha1-kEFwfWIkE2f1iDRTK58ZwsNvrHg=",
|
||||
"requires": {
|
||||
"JSONSelect": "0.4.0",
|
||||
"cjson": "0.2.1",
|
||||
"ebnf-parser": "0.1.10",
|
||||
"escodegen": "0.0.21",
|
||||
"esprima": "1.0.4",
|
||||
"jison-lex": "0.2.1",
|
||||
"JSONSelect": "0.4.0",
|
||||
"lex-parser": "0.1.4",
|
||||
"nomnom": "1.5.2"
|
||||
},
|
||||
@@ -7961,11 +7971,6 @@
|
||||
"resolved": "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz",
|
||||
"integrity": "sha1-T9kss04OnbPInIYi7PUfm5eMbLk="
|
||||
},
|
||||
"JSONSelect": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/JSONSelect/-/JSONSelect-0.4.0.tgz",
|
||||
"integrity": "sha1-oI7cxn6z/L6Z7WMIVTRKDPKCu40="
|
||||
},
|
||||
"jsprim": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.0.tgz",
|
||||
@@ -8009,11 +8014,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"JSV": {
|
||||
"version": "4.0.2",
|
||||
"resolved": "https://registry.npmjs.org/JSV/-/JSV-4.0.2.tgz",
|
||||
"integrity": "sha1-0Hf2glVx+CEy+d/67Vh7QCn+/1c="
|
||||
},
|
||||
"jsx-ast-utils": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-2.0.1.tgz",
|
||||
@@ -9069,6 +9069,11 @@
|
||||
"integrity": "sha1-tDiTYhcOfvl5jDx3FtgOvAEG/M8=",
|
||||
"dev": true
|
||||
},
|
||||
"oauth-1.0a": {
|
||||
"version": "2.2.2",
|
||||
"resolved": "https://registry.npmjs.org/oauth-1.0a/-/oauth-1.0a-2.2.2.tgz",
|
||||
"integrity": "sha512-fHRvq3aHoYXq8rZrXOX80nYgMc0svd4a88R4W7QLltJ1Rl+GFjW6Eu3rgR1zWB5MbuyqsWojADsS4vbmDiho/w=="
|
||||
},
|
||||
"oauth-sign": {
|
||||
"version": "0.8.2",
|
||||
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.8.2.tgz",
|
||||
@@ -11753,11 +11758,6 @@
|
||||
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=",
|
||||
"dev": true
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
|
||||
},
|
||||
"string-length": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/string-length/-/string-length-1.0.1.tgz",
|
||||
@@ -11783,6 +11783,11 @@
|
||||
"integrity": "sha1-aybpvTr8qnvjtCabUm3huCAArHg=",
|
||||
"dev": true
|
||||
},
|
||||
"string_decoder": {
|
||||
"version": "0.10.31",
|
||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
|
||||
"integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ="
|
||||
},
|
||||
"stringstream": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/stringstream/-/stringstream-0.0.5.tgz",
|
||||
|
||||
@@ -150,6 +150,7 @@
|
||||
"nedb": "^1.8.0",
|
||||
"node-forge": "^0.7.0",
|
||||
"nunjucks": "^3.0.0",
|
||||
"oauth-1.0a": "^2.2.2",
|
||||
"pdfjs-dist": "^1.9.640",
|
||||
"prop-types": "^15.5.10",
|
||||
"react": "^16.0.0",
|
||||
|
||||
Reference in New Issue
Block a user