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

AIP-X Sign in with Aptos #556

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open

Conversation

aptqpv
Copy link

@aptqpv aptqpv commented Jan 29, 2025

Description

Initial draft for Sign in with Aptos, a standard for secure and user-friendly way to authenticate to off-chain resources using Aptos blockchain addresses.

@thepomeranian thepomeranian requested a review from alinush January 29, 2025 02:36

Addressing these challenges is key to unlocking the full potential of decentralized authentication and delivering a seamless, secure, and user-friendly experience.

![Figure 1: Sign in with Aptos](./static/8.png)
Copy link
Contributor

@alinush alinush Jan 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A phishing.com domain should NOT even be allowed to ask the user for a SIWA signature for dapp.xyz.

This picture suggests that it can.

I see no benefit to doing this; only problems. Can we change this please?

For example, a user may choose to use one of the wallet experiences to authenticate into an application:

- **Petra** – _Passwords/Biometric_: - Fully non-custodial. Requires no personal information, ensuring complete privacy and resistance to censorship.
- **Aptos Connect** – _Social Providers_: Fully non-custodial. Shares limited personal information like name and email but may be subject to censorship by social providers.
Copy link
Contributor

@alinush alinush Jan 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please clarify who is sharing information with whom! I think you mean that the user is sharing its info (i.e., JWT) with AC.

Like we discussed before, I find this confusing: the chain / dapp does not learn anything, actually.

Of course, the wallet (i.e., AC) sees the JWT and learns your OIDC identity. I wouldn't necesarily call that "personal information" though; it's too broad. It's more helpful to be specific and say what it is: "name, profile picture, email, OIDC sub"

aips/aip-x.md Show resolved Hide resolved

However, while this approach offers significant benefits, it also presents several challenges:

1. **Lack of standardization:** Applications on Aptos lack a unified authentication message format, leading to inconsistencies that confuse users.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missed opportunity: Refer the reader to your screenshot that beautifully showcases this. Showing is better than telling.

1. **Lack of standardization:** Applications on Aptos lack a unified authentication message format, leading to inconsistencies that confuse users.
2. **Unreadable messages:** Authentication messages are displayed in plaintext, making them difficult for users to comprehend.
3. **Limited wallet support:** Without standardization, wallets cannot effectively support authentication UIs.
4. **Security risks:** Malicious websites can deceive users into signing messages intended for legitimate dApps.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't the signMessage flow domain-separated? Doesn't it include the requesting dapp's URL in the signed message? I guess it is optional?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you point via URL to AIP-62's *MessageInput structs with the optional application field, for extra clarity.

2. **Unreadable messages:** Authentication messages are displayed in plaintext, making them difficult for users to comprehend.
3. **Limited wallet support:** Without standardization, wallets cannot effectively support authentication UIs.
4. **Security risks:** Malicious websites can deceive users into signing messages intended for legitimate dApps.
5. **Unintuitive processes:** The traditional `connect` + `signMessage` workflow involves two separate steps, creating a clunky and unintuitive user experience.
Copy link
Contributor

@alinush alinush Jan 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explain what are these two steps in parentheses.

Copy link
Contributor

@alinush alinush Jan 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it connect + signMessage?

I didn't initially understand how the connect step disappears. I suppose with SIWA, when you click "Connect wallet" you'll just get the signIn request before the wallet is actually connected, thereby merging everything into one step?

If so, this may be worth depicting via pictures & explaining.

5. **Unintuitive processes:** The traditional `connect` + `signMessage` workflow involves two separate steps, creating a clunky and unintuitive user experience.

Addressing these challenges is key to unlocking the full potential of decentralized authentication and delivering a seamless, secure, and user-friendly experience.

Copy link
Contributor

@alinush alinush Jan 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The image appears suddenly, without any context or explanation.

Maybe move it in its own [sub]section and explain what the image showcases.

aips/aip-x.md Show resolved Hide resolved
| version | string | | Current version of the message. |
| statement | string | | Human-readable ASCII assertion that the user will sign. It MUST NOT contain `\n`. |
| nonce | string | | Randomized token to prevent signature replay attacks. |
| chainId | string | | Identifier for the network locating the address listed separately above. |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"Identifier for the network locating the address listed separately above"
-->
"Identifier for the network where the address above lives (e.g., for Aptos mainnet, the chain ID would be 1)"


| Name | Type | Mandatory | Description |
| --------------------- | --------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------- |
| fields.domain | string | ✓ | `dnsauthority` that is requesting the signing |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From the text, it is not clear: is AptosSignInMessage::fields.domain set to AptosSignInInput::domain?

I am a bit confused as to why you are you re-stating the same fields here.

Is there a less redundant way to describe this? May need to meet to clarify.

| ----------------- | ------------- | --------- | ---------------------------------------------------------------------------------------------------------------------------------- |
| account.address | string | ✓ | The address of the user that is signing in. |
| account.publicKey | PublicKey | ✓ | The public key of the user that is signing in. |
| message | SignInMessage | ✓ | A SignInMessage object that contains information about the message that was signed, it's signature, and plain text representation. |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this SignInMessage or AptosSignInMessage?

| fields.requestId | string | | System-specific identifier used to uniquely refer to the authentication request. |
| fields.resources | string[] | | List of information or references to information the user wishes to have resolved as part of the authentication by the relying party. |
| plainText | string | ✓ | The constructed message using the standardized message format. |
| signature | bytes | ✓ | The signature of the message. This must conform to the domain separated signing algorithm. |
Copy link
Contributor

@alinush alinush Jan 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So there's a signature here over (some serialization of) AptosSignInMessage?

| account.address | string | ✓ | The address of the user that is signing in. |
| account.publicKey | PublicKey | ✓ | The public key of the user that is signing in. |
| message | SignInMessage | ✓ | A SignInMessage object that contains information about the message that was signed, it's signature, and plain text representation. |
| signature | Signature | ✓ | The signature of the message. |
Copy link
Contributor

@alinush alinush Jan 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we already had a signature above over (some serialization of) AptosSignInMessage, then what is this signature?


```
example.com wants you to sign in with your Aptos account:
0x0000000000000000000000000000000000000000000000000000000000000001
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think 0x000...0001 is a good example here: it will never arise in practice.

- resource2
```

### Augment Backus-Naur Form (ABNF) Expression
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Augmented

Chain ID: mainnet
```

_Detailed Example_
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be very helpful if this AIP described when field like nonce should be set in the message.

This section on examples could be a good place to do that: go over a few sample messages and detail an application where that message suffices. I am actually wondering where the "minimal example" above would actually arise.

message-resources = \\*( LF "- " URI )
```

### Domain Separating Signing Algorithm
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Domain-separated signing algorithm

```
sha3_256(b"SIGN_IN_WITH_APTOS::") || <siwa_message>
```

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add the following clarification:

where <siwa_message> is a sign-in with Aptos message formatted as explained in "Message Format" above.


### Wallet Standard

The [Wallet Standard](https://github.com/aptos-labs/wallet-standard) is a chain-agnostic set of interfaces and conventions that aim to improve how applications interact with injected wallets.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are you explaining what the wallet standard is because you are about to propose a modification/extension of it?

If so, maybe clarify from the beginning:

"This AIP also modifies / extends the wallet standard, which is a chain-agnostic set of [...]"


#### Suggested Features

The features below will be added to the wallet as suggested features. Features will be optional to maintain compatibility with existing wallets.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

*to the wallet standard

no?


### Wallet Implementer

To ensure the safety of our users, we want to take a conservative approach when allowing users to sign potentially harmful messages.
Copy link
Contributor

@alinush alinush Jan 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't be both "allowing users to sign potentially-harmful messages" and "take a conservative approach."

They are kind of in contradiction 😛

I propose we nix the 1st and only do the 2nd :)


#### Bound Fields Verification

The following fields MUST be verified to prevent phishing attacks: `domain` , `address` , `uri` , `version` , and `chainId` . If the fields do not match the signing request, errors must be displayed to the users detailing them out. It is suggested to add additional steps to the approval process, such as an opt-in checkmark field, that confirms the user’s intent if errors are present.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Saying that "fields MUST be verified" is not precise:

  1. Who is doing the verification?
  2. What exactly is this verification for each field?


The following fields MUST be verified to prevent phishing attacks: `domain` , `address` , `uri` , `version` , and `chainId` . If the fields do not match the signing request, errors must be displayed to the users detailing them out. It is suggested to add additional steps to the approval process, such as an opt-in checkmark field, that confirms the user’s intent if errors are present.

A wallet may also decide to prevent the approval of invalid signing requests.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a MUST, not a may.


#### @aptos-labs/siwa

A new package named `@aptos-labs/siwa` will be created to house the utilities for the _Sign in with Aptos_ standard. These utilities will be responsible for creating messages, verifying messages, and deserializing public key and/or signatures according.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NPM package? What kind of package?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What language?


```ts
/**
* Create a SignIn message text from the input following the ABNF format defined in the Sign in with Aptos
Copy link
Contributor

@alinush alinush Jan 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pro-tip: In technical writing, you always want to refer to the same thing by one name. It can't be either of SignMessage, AptosSignInMessage or SignIn message. You have to pick one and use it consistently. This way, the term is drilled down into your reader's head and they will know what you mean every time.

function createSignInMessageText(input: AptosSignInMessage["fields"]): string;

/**
* Verifies an input SignIn message against expected fields.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same problem here.


### AptosSignInOutput

When the user has approved and signed the message, the wallet will respond with an `AptosSignInOutput` to the application. The application should then use this response to verify if the outputs are valid with the inputs.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unclear what this means: "verify if the outputs are valid with the inputs."

): VerificationResult<AptosSignInMessage["fields"]>;

/**
* Generate a signing message using the Sign in with Aptos signing algorithm.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is a "signing message" different than a "[Aptos]SignInMessage"?

If so, did the AIPs text properly introduce both & differentiate between them? I don't think "signing message" has been introduced.

* Generate a signing message using the Sign in with Aptos signing algorithm.
* sha3_256( sha3_256(b"SIGN_IN_WITH_APTOS::" ) || <message> )
*
* @param message The SIWA message to sign.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, what is "SIWA message"? It looks like another unnecessary synonym.


#### @aptos-labs/wallet-standard

The following interfaces would be introduced into the `@aptos-labs/wallet-standard` package.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Include a link to it here, please.

resources?: string[];
};

export type AptosSignInMessage = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you should solely use this AptosSignInMessage term throughout the text, instead of synonyms for it.


### Wallet Implementation

The wallet is responsible for taking `AptosSignInInput` fields defined by an an application and returning a response object with a signature, plain text representation of the message, and account information.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: "an an" --> an

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is a "response object"? Again, no synonyms.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is "the message"?


The wallet is responsible for taking `AptosSignInInput` fields defined by an an application and returning a response object with a signature, plain text representation of the message, and account information.

The wallet must bind the `address`, `chainId` , `domain` , `uri` , and `version` fields if not present. If there is a mismatch between these fields and the ones defined by the application, it is important that it is flagged and shown to the user.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I understand what "bind" means. You mean "set to the correct value"?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, "flagged" is not good enough. It must be forbidden.

}
```

2. The Wallet will construct a `AptosSignInMessage` with the input. The `createSignInMessageText` utility from `@aptos-labs/siwa` can be used. Once the plaintext representation of the message has been constructed, we want to generate a signing message using `generateSignInSigningMessage` that conforms to _Sign in with Aptos_’s domain separated signing algorithm. **It is important to bind the following fields: `address`, `chainId` , `domain`, `uri` , and `version`.**
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: will construct an AptosSignInMessage

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As mentioned before, not sure if bind is the right word here. If it is, it may be worth clarifying this earlier in the AIP.


### Application Implementation

The application will be responsible for sending the `signIn` request with `AptosSignInput` fields to the wallet. The application should typically create the fields in the backend and store them to verified at the end of the flow.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo: AptosSignInput --> AptosSignInRequest

Copy link
Contributor

@alinush alinush Jan 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A couple of high level thoughts:

  • AptosSignInInput is not as descriptive of a name as AptosSignInRequest, no? It is a request, no?
  • I propose you replace AptosSignIn with SiWA or SIWA everywhere. Not only less verbose, but also more to the point: this AIP is about SIWA.
  • There is quite a bit of terminology here and the AIP currently uses too many names for the same term. This has to be fixed: one term, one name.
  • You may even want to have a section where you overview the terminology. Not sure.
  • I think the "High-level overview" should actually overview what is happening in SIWA: dapp makes a request to a wallet (in a certain format), wallet displays a prompt to the user, user clicks approve, wallet signs (in a certain format), dapp gets signature.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I should've also highlighted the things you did very well when writing this AIP:

  • Well-structured
  • Writing is generally good
  • Figures / screenshots / illustrations 👌👌👌
  • Nice tables describing the formats
  • You included a formal description of the grammar
  • Code examples
  • Lots of examples in general


The wallet must bind the `address`, `chainId` , `domain` , `uri` , and `version` fields if not present. If there is a mismatch between these fields and the ones defined by the application, it is important that it is flagged and shown to the user.

#### Overview
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I found this hard to read / understand. Not a TS guy so that may be why. But there may also be too many things here. Do you need all of this? Can anything be left out / simplified?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably otherwise a very good section for TS devs / wallet devs / dapps devs.


## Testing

The new `@aptos-labs/siwa` package will have its utilities tested to ensure that validation is done correctly. Coverage is most important here. In addition, signature verification methods will be used from the `@aptos-labs/ts-sdk`, it's important that public key verification methods are supported and tested.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it's important that public key verification methods are supported and tested

What are you referring to here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After convo: You mean "signature verification" (which takes a message m, a public key pk and a signature \sigma as input and outputs either 0 or 1)


## Risks and Drawbacks

The ecosystem is responsible for adopting the new standard as an alternative to the `connect` + `signMessage` flow. If applications/wallets do not properly implement the `signIn` flow, they may suffer vulnerabilities that can lead to potential phishing, replay, or forgery attacks. If vulnerabilities are found within _Aptos Labs_ or ecosystem utilities, it’s important to patch and deprecate them as soon as possible. Applications that accept the `connect` + `signMessage` flow may still be vulnerable to security attacks.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If applications/wallets do not properly implement the signIn flow, they may suffer vulnerabilities that can lead to potential phishing, replay, or forgery attacks.

I think the AIP actually needs to discuss ways in which applications can mess this up. Ideally, there should not be (m?)any.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If vulnerabilities are found within Aptos Labs or ecosystem utilities, it’s important to patch and deprecate them as soon as possible.

This is self-evident. Not sure why you are stating it here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Regarding #1:

I think the only opportunities to mess this up are:

  • the application does not pick the nonce randomly (but even this the TS SDK could fix, by not even letting the application pick the nonce, no?)
  • the session management via cookies


The attack vectors that must be accounted for are the following:

- Phishing attacks — A user must have visibility on signing a message that is for a different application.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Such a phishing prompt should never be shown to the user. (So, really, the user should not have any visibility into this.)


## Future Potential

This AIP formally introduces a standard for authentication via Aptos decentralized identities. In the future, the standard may be extended to provide additional information from the wallet.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"via Aptos decentralized identities."

This is not precise. Unclear what "decentralized identity" means. It's a fluff umbrella term, AFAICT.

"via Aptos accounts" would be precise.


This AIP formally introduces a standard for authentication via Aptos decentralized identities. In the future, the standard may be extended to provide additional information from the wallet.

With the rise of Keyless on the Aptos Blockchain, wallet connections may want to be extended to provide additional personal information about the user, this would include full names, phone numbers, or emails.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could actually be made possible using the extra_field feature of the keyless ZKP (see AIP-61).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(no need to riff on this in this AIP)


## High-level Overview

**Decentralized authentication** is a privacy-first solution that empowers individuals to safeguard their information, personalize their experiences, and maintain freedom from censorship.
Copy link
Contributor

@alinush alinush Jan 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this AIP is about decentralized authentication, nor privacy-first anything...

  • there are no privacy benefits here over the connect + signIn baseline, right?
  • "Decentralized authentication" sounds like a vague umbrella term to me

This AIP is about users signing into a dapp using their Aptos account and, as a result, getting access to protected resources.

| signature | bytes | ✓ | The signature of the message. This must conform to the domain separated signing algorithm. |
| type | string | ✓ | The public key scheme used to sign the message (e.g. 'ed25519', 'single_key', 'multi_key', 'multi_ed25519', etc.) |

### AptosSignInOutput
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this generic "output" name. Shouldn't this be something more like a AptosSignInSignature or SiwaSignature?

sha3_256(b"SIGN_IN_WITH_APTOS::") || <siwa_message>
```

### Wallet Standard
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Retitle: Modifications to the wallet standard

signIn(input: AptosSignInInput): Promise<UserResponse<AptosSignInOutput>>
```

### Wallet Implementer
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Retitle: How to implement this AIP safely as a wallet developer

| uri | string | | URI referring to the resource that is the subject of the signing i.e. the subject of the claim. |
| version | string | | Current version of the message. |
| statement | string | | Human-readable ASCII assertion that the user will sign. It MUST NOT contain `\n`. |
| nonce | string | | Randomized token to prevent signature replay attacks. |
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This feels like it should be mandatory, AFAIU.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants