Skip to content

Commit

Permalink
Improves server side functionality (spruceid#3)
Browse files Browse the repository at this point in the history
* External validate function and option to fetch nonce

* Add missing dependency

* Remove extra line from message

* Add EIP1271 support

* Message validation

* Refactor to use etherjs

* Fixes error handling

* Make currentSession optional

* Adds the retrieval of ensAvatar and includes it in session if available

* Removes front-end specific code (spruceid#4)

* Removes front-end specific code

* Fixes validation

* Removed pubkey field

* Improved validation error message

* Removed unsued field

* Removed unused dependency

* Add docs

* Fix for basePath

* Fix jest error

* Fix to base path

* Fix path script

* Removed base path script

Co-authored-by: K Rhoda <[email protected]>
  • Loading branch information
w4ll3 and krhoda authored Nov 10, 2021
1 parent c02a245 commit 85408df
Show file tree
Hide file tree
Showing 10 changed files with 5,080 additions and 19,705 deletions.
2 changes: 1 addition & 1 deletion .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ indent_style = tab
[lib/**.ts]
indent_style = tab
indent_size = 4
max_line_length = 120
max_line_length = 80
quote_type = single
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
node_modules
dist
dist
docs
35 changes: 34 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1,34 @@
# Sign-In with Ethereum
![Sign-In with Ethereum logo](https://login.xyz/favicon.png "Sign-In with Ethereum logo")

Sign-In with Ethereum describes how Ethereum accounts authenticate with
off-chain services by signing a standard message format parameterized by scope,
session details, and security mechanisms (e.g., a nonce). The goals of this
specification are to provide a self-custodied alternative to centralized
identity providers, improve interoperability across off-chain services for
Ethereum-based authentication, and provide wallet vendors a consistent
machine-readable message format to achieve improved user experiences and
consent management.

## Motivation
When signing in to popular non-blockchain services today, users will typically
use identity providers (IdPs) that are centralized entities with ultimate
control over users' identifiers, for example, large internet companies and email
providers. Incentives are often misaligned between these parties. Sign-In with
Ethereum offers a new self-custodial option for users who wish to assume more
control and responsibility over their own digital identity.

Already, many services support workflows to authenticate Ethereum accounts using
message signing, such as to establish a cookie-based web session which can
manage privileged metadata about the authenticating address. This is an
opportunity to standardize the sign-in workflow and improve interoperability
across existing services, while also providing wallet vendors a reliable method
to identify signing requests as Sign-In with Ethereum requests for improved UX.

This work is sponsored by the Ethereum Foundation and Ethereum Name Service
(ENS). It is being developed in the open through a series of recorded community
calls and public repositories, and its development is informed by over twenty
user interviews with a focus on currently-in-production uses, related prior
EIPs, and fits within product roadmaps.

## Specification
Specification can be found at the [EIP-4361 GitHub page](https://github.com/ethereum/EIPs/blob/9a9c5d0abdaf5ce5c5dd6dc88c6d8db1b130e95b/EIPS/eip-4361.md).
20 changes: 20 additions & 0 deletions favicon.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
155 changes: 131 additions & 24 deletions lib/abnf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,100 +178,207 @@ export class ParsedMessage {
parser.ast = new apgLib.ast();
const id = apgLib.ids;

const domain = function(state, chars, phraseIndex, phraseLength, data) {
const domain = function (
state,
chars,
phraseIndex,
phraseLength,
data
) {
const ret = id.SEM_OK;
if (state === id.SEM_PRE) {
data.domain = apgLib.utils.charsToString(chars, phraseIndex, phraseLength);
data.domain = apgLib.utils.charsToString(
chars,
phraseIndex,
phraseLength
);
}
return ret;
};
parser.ast.callbacks.domain = domain;
const address = function(state, chars, phraseIndex, phraseLength, data) {
const address = function (
state,
chars,
phraseIndex,
phraseLength,
data
) {
const ret = id.SEM_OK;
if (state === id.SEM_PRE) {
data.address = apgLib.utils.charsToString(chars, phraseIndex, phraseLength);
data.address = apgLib.utils.charsToString(
chars,
phraseIndex,
phraseLength
);
}
return ret;
};
parser.ast.callbacks.address = address;
const statement = function(state, chars, phraseIndex, phraseLength, data) {
const statement = function (
state,
chars,
phraseIndex,
phraseLength,
data
) {
const ret = id.SEM_OK;
if (state === id.SEM_PRE) {
data.statement = apgLib.utils.charsToString(chars, phraseIndex, phraseLength);
data.statement = apgLib.utils.charsToString(
chars,
phraseIndex,
phraseLength
);
}
return ret;
};
parser.ast.callbacks.statement = statement;
const uri = function(state, chars, phraseIndex, phraseLength, data) {
const uri = function (state, chars, phraseIndex, phraseLength, data) {
const ret = id.SEM_OK;
if (state === id.SEM_PRE) {
if (!data.uri) {
data.uri = apgLib.utils.charsToString(chars, phraseIndex, phraseLength);
data.uri = apgLib.utils.charsToString(
chars,
phraseIndex,
phraseLength
);
}
}
return ret;
};
parser.ast.callbacks.uri = uri;
const version = function(state, chars, phraseIndex, phraseLength, data) {
const version = function (
state,
chars,
phraseIndex,
phraseLength,
data
) {
const ret = id.SEM_OK;
if (state === id.SEM_PRE) {
data.version = apgLib.utils.charsToString(chars, phraseIndex, phraseLength);
data.version = apgLib.utils.charsToString(
chars,
phraseIndex,
phraseLength
);
}
return ret;
};
parser.ast.callbacks.version = version;
const chainId = function(state, chars, phraseIndex, phraseLength, data) {
const chainId = function (
state,
chars,
phraseIndex,
phraseLength,
data
) {
const ret = id.SEM_OK;
if (state === id.SEM_PRE) {
data.chainId = apgLib.utils.charsToString(chars, phraseIndex, phraseLength);
data.chainId = apgLib.utils.charsToString(
chars,
phraseIndex,
phraseLength
);
}
return ret;
};
parser.ast.callbacks['chain-id'] = chainId;
const nonce = function(state, chars, phraseIndex, phraseLength, data) {
const nonce = function (state, chars, phraseIndex, phraseLength, data) {
const ret = id.SEM_OK;
if (state === id.SEM_PRE) {
data.nonce = apgLib.utils.charsToString(chars, phraseIndex, phraseLength);
data.nonce = apgLib.utils.charsToString(
chars,
phraseIndex,
phraseLength
);
}
return ret;
};
parser.ast.callbacks.nonce = nonce;
const issuedAt = function(state, chars, phraseIndex, phraseLength, data) {
const issuedAt = function (
state,
chars,
phraseIndex,
phraseLength,
data
) {
const ret = id.SEM_OK;
if (state === id.SEM_PRE) {
data.issuedAt = apgLib.utils.charsToString(chars, phraseIndex, phraseLength);
data.issuedAt = apgLib.utils.charsToString(
chars,
phraseIndex,
phraseLength
);
}
return ret;
};
parser.ast.callbacks['issued-at'] = issuedAt;
const expirationTime = function(state, chars, phraseIndex, phraseLength, data) {
const expirationTime = function (
state,
chars,
phraseIndex,
phraseLength,
data
) {
const ret = id.SEM_OK;
if (state === id.SEM_PRE) {
data.expirationTime = apgLib.utils.charsToString(chars, phraseIndex, phraseLength);
data.expirationTime = apgLib.utils.charsToString(
chars,
phraseIndex,
phraseLength
);
}
return ret;
};
parser.ast.callbacks['expiration-time'] = expirationTime;
const notBefore = function(state, chars, phraseIndex, phraseLength, data) {
const notBefore = function (
state,
chars,
phraseIndex,
phraseLength,
data
) {
const ret = id.SEM_OK;
if (state === id.SEM_PRE) {
data.notBefore = apgLib.utils.charsToString(chars, phraseIndex, phraseLength);
data.notBefore = apgLib.utils.charsToString(
chars,
phraseIndex,
phraseLength
);
}
return ret;
};
parser.ast.callbacks['not-before'] = notBefore;
const requestId = function(state, chars, phraseIndex, phraseLength, data) {
const requestId = function (
state,
chars,
phraseIndex,
phraseLength,
data
) {
const ret = id.SEM_OK;
if (state === id.SEM_PRE) {
data.requestId = apgLib.utils.charsToString(chars, phraseIndex, phraseLength);
data.requestId = apgLib.utils.charsToString(
chars,
phraseIndex,
phraseLength
);
}
return ret;
};
parser.ast.callbacks['request-id'] = requestId;
const resources = function(state, chars, phraseIndex, phraseLength, data) {
const resources = function (
state,
chars,
phraseIndex,
phraseLength,
data
) {
const ret = id.SEM_OK;
if (state === id.SEM_PRE) {
data.resources = apgLib.utils.charsToString(chars, phraseIndex, phraseLength).slice(3).split('\n- ');
data.resources = apgLib.utils
.charsToString(chars, phraseIndex, phraseLength)
.slice(3)
.split('\n- ');
}
return ret;
};
Expand Down
Loading

0 comments on commit 85408df

Please sign in to comment.