Skip to content
Permalink
Browse files

feat(Auth): add new Auth resource

  • Loading branch information...
satello committed May 1, 2018
1 parent 2e5747a commit 5ad300b918bbeab8d9730345fb0c33d83c87f617
@@ -9,11 +9,7 @@
],
"main": "lib/index.js",
"module": "es/index.js",
"files": [
"es",
"lib",
"umd"
],
"files": ["es", "lib", "umd"],
"homepage": "https://kleros.io",
"repository": "github:kleros/kleros-api",
"bugs": "https://github.com/kleros/kleros-api/issues",
@@ -36,12 +32,11 @@
"commitmsg": "kleros-scripts commitmsg",
"cz": "kleros-scripts cz",
"start": "babel src --out-dir ./es --watch --source-maps",
"build": "rimraf ./umd ./es ./lib && webpack --env.NODE_ENV=production -p && babel src --out-dir ./es --source-maps && cross-env BABEL_ENV=commonjs babel src --out-dir ./lib --source-maps"
"build":
"rimraf ./umd ./es ./lib && webpack --env.NODE_ENV=production -p && babel src --out-dir ./es --source-maps && cross-env BABEL_ENV=commonjs babel src --out-dir ./lib --source-maps"
},
"commitlint": {
"extends": [
"@commitlint/config-conventional"
]
"extends": ["@commitlint/config-conventional"]
},
"devDependencies": {
"babel-cli": "^6.26.0",
@@ -67,6 +62,7 @@
},
"dependencies": {
"babel-runtime": "^6.26.0",
"eth-sig-util": "^1.4.2",
"kleros": "^0.0.5",
"kleros-interaction": "^0.0.8",
"lodash": "^4.17.4",
@@ -147,7 +147,6 @@ class ContractImplementation {
this._contractLoadedRejecter = reject
})

// we have getters so that abstract classes can provide public access to implementations variables
/**
* Get the contract address for the currently instantiated contract.
* @returns {string} - The address of the contract.
@@ -33,12 +33,14 @@ class Kleros {
* use when initializing KlerosPOC
* @param {string} arbitrableContractAddress - Address of the arbitrator contract we should
* use when initializing KlerosPOC
* @param {string} authToken - Signed token cooresponding to the user profile address.
*/
constructor(
ethereumProvider = isRequired('ethereumProvider'),
storeUri = isRequired('storeUri'),
arbitratorAddress,
arbitrableContractAddress
arbitrableContractAddress,
authToken
) {
// NOTE we default to KlerosPOC and ArbitrableTransaction
const _klerosPOC = new contracts.implementations.arbitrator.KlerosPOC(
@@ -55,7 +57,7 @@ class Kleros {
// **************************** //
// KLEROS WRAPPERS
this.web3Wrapper = new Web3Wrapper(ethereumProvider)
this.storeWrapper = new StoreProviderWrapper(storeUri)
this.storeWrapper = new StoreProviderWrapper(storeUri, authToken)
// ARBITRATOR
this.arbitrator = new contracts.abstractions.Arbitrator(
_klerosPOC,
@@ -78,6 +80,8 @@ class Kleros {
this.arbitrable,
this.storeWrapper
)
// AUTH
this.auth = new resources.Auth(this.web3Wrapper, this.storeWrapper)
}

/**
@@ -137,6 +141,7 @@ class Kleros {
this.arbitrable.setStoreProviderInstance(this.storeWrapper)
this.arbitrator.setStoreProviderInstance(this.storeWrapper)
this.notifications.setStoreProviderInstance(this.storeWrapper)
this.auth.setStoreProviderInstance(this.storeWrapper)
}
}

@@ -0,0 +1,54 @@
import isRequired from '../utils/isRequired'

class Auth {
constructor(
web3Wrapper = isRequired('web3Wrapper'),
storeProviderInstance = isRequired('storeProviderInstance')
) {
this._Web3Wrapper = web3Wrapper
this._StoreProviderInstance = storeProviderInstance
}

/**
* Set store provider instance.
* @param {object} storeProviderInstance - instance of store provider wrapper.
*/
setStoreProviderInstance = storeProviderInstance => {
this._StoreProviderInstance = storeProviderInstance
}

/**
* Set an auth token in the Store Provider. Call this instead of validateNewAuthToken
* if you have a signed token saved.
* @param {string} token - Hex representation of signed token.
*/
setAuthToken = token => {
this._StoreProviderInstance.setAuthToken(token)
}

/**
* Validate a new auth token. Note if you validate a new token old signed tokens
* will not longer be valid regardless of their expiration time.
* @param {string} userAddress - Address of the user profile
* @returns {string} Signed token for future use.
*/
validateNewAuthToken = async userAddress => {
const unsignedToken = await this._StoreProviderInstance.newAuthToken(
userAddress
)

const signedToken = this.signMessage(userAddress, unsignedToken)
this.setAuthToken(signedToken)
return signedToken
}

/**
* Sign a message with your private key.
* @param {string} userAddress - The address with which we want to sign the message
* @param {string} data - Hex encoded data to sign
* @returns {string} signed data
*/
signMessage = (userAddress, data) => this._Web3Wrapper.sign(userAddress, data)
}

export default Auth
@@ -1,4 +1,5 @@
import Disputes from './Disputes'
import Notifications from './Notifications'
import Auth from './Auth'

export { Disputes, Notifications }
export { Disputes, Notifications, Auth }
@@ -11,9 +11,11 @@ class StoreProviderWrapper {
/**
* Create a new instance of StoreProviderWrapper.
* @param {string} storeProviderUri - The uri of kleros store.
* @param {string} authToken - Signed token cooresponding to user profile address.
*/
constructor(storeProviderUri) {
constructor(storeProviderUri, authToken) {
this._storeUri = storeProviderUri
this._token = authToken
this._storeQueue = new PromiseQueue()
}

@@ -25,6 +27,12 @@ class StoreProviderWrapper {
* @returns {Promise} request promise that resolves to the HTTP response.
*/
_makeRequest = (verb, uri, body = null) => {
if (verb !== 'GET' && !this._token) {
throw new Error(
'No auth token set. Cannot make writes to store. Please call setAuthToken or validateNewAuthToken.'
)
}

const httpRequest = new XMLHttpRequest()
return new Promise((resolve, reject) => {
try {
@@ -34,6 +42,7 @@ class StoreProviderWrapper {
'Content-Type',
'application/json;charset=UTF-8'
)
httpRequest.setRequestHeader('Authorization', this._token)
}
httpRequest.onreadystatechange = () => {
if (httpRequest.readyState === 4) {
@@ -75,6 +84,31 @@ class StoreProviderWrapper {
queueReadRequest = uri =>
this._storeQueue.fetch(() => this._makeRequest('GET', uri))

// **************************** //
// * Auth * //
// **************************** //

/**
* Set the auth token for write requests.
* @param {string} token - Hex string of the signed data token.
*/
setAuthToken = token => {
this._token = token
}

/**
* Generate a new unsigned auth token.
* @param {string} userAddress - Address of the user profile.
* @returns {string} Hex encoded unsigned token.
*/
newAuthToken = async userAddress => {
const newTokenResponse = await this._makeRequest(
'GET',
`${this._storeUri}/${userAddress}`
)

return newTokenResponse.body
}
// **************************** //
// * Read * //
// **************************** //
@@ -32,6 +32,8 @@ class Web3Wrapper {

blockNumber = () => this._web3.eth.blockNumber

sign = (userAddress, data) => this._web3.eth.sign(userAddress, data)

getBlock = blockNumber =>
new Promise((resolve, reject) => {
this._web3.eth.getBlock(blockNumber, (error, result) => {
@@ -0,0 +1,59 @@
import Web3 from 'web3'
import sigUtil from 'eth-sig-util'

import Kleros from '../../src/kleros'
import * as ethConstants from '../../src/constants/eth'

describe('Auth', () => {
let loggedInUserAddress

beforeAll(async () => {
const provider = await new Web3.providers.HttpProvider(
ethConstants.LOCALHOST_ETH_PROVIDER
)
const web3 = await new Web3(provider)

loggedInUserAddress = web3.eth.accounts[0]
})

it('can sign auth token', async () => {
const mockStoreUri = ''
const ethProvider = new Web3.providers.HttpProvider(
ethConstants.LOCALHOST_ETH_PROVIDER
)
const mockArbitrator = '0x0'
const mockArbitrable = '0x1'

const klerosInstance = new Kleros(
ethProvider,
mockStoreUri,
mockArbitrator,
mockArbitrable
)

const mockToken =
'0x7b2276657273696f6e223a312c2265787069726174696f6e223a313532353830303831313932307d'
const mockStoreProvider = {
newAuthToken: () => mockToken,
setAuthToken: () => true
}
// set new store provider
klerosInstance.auth.setStoreProviderInstance(mockStoreProvider)

const signedToken = await klerosInstance.auth.validateNewAuthToken(
loggedInUserAddress
)

expect(signedToken).toBeTruthy()

// validate token
const msgParams = {
data: mockToken,
sig: signedToken
}

const authorizedUser = await sigUtil.recoverPersonalSignature(msgParams)

expect(authorizedUser).toEqual(loggedInUserAddress)
})
})
Oops, something went wrong.

0 comments on commit 5ad300b

Please sign in to comment.
You can’t perform that action at this time.