Skip to content

Releases: kristoferlund/ic-siwe

ic-siwe-js: v0.2.4

18 Jan 21:38
0ca85be

Choose a tag to compare

Added

  • Support for Vue.

Usage with Vue

The Vue submodule comes with SiweIdentityProvider that makes the SiweManager available to all components in the app. It also provides a useSiwe hook that can be used to interact with the SiweManager instance.

1. Setup the SiweIdentityProvider component

In the App.vue component, initiate the SiweIdentityProvider with a reference to the SIWE provider canister to make it available to all child components.

<script setup lang="ts">

import { createSiweIdentityProvider } from "ic-siwe-js/vue";
import { canisterId } from "../../ic_siwe_provider/declarations/index";

createSiweIdentityProvider({
  canisterId,
});

</script>

<template>
    <!-- Your app components -->
</template>

2. Initiate the login process

The login process is initiated by calling the login function. This function requests a SIWE message from the backend if it has not already been loaded. The user is asked to sign the message using their Ethereum wallet and the signed message is sent to the backend for authentication. Once the authentication is complete, the user's identity is stored in local storage and the identity state variable is updated with the new identity.

The loginStatus state variable can be used to indicate the status of the login process. Errors that occur during the login process are stored in the loginError state variable.

<script setup lang="ts">
import { useSiwe } from "ic-siwe-js/vue";

const siwe = useSiwe();

</script>

<template>
  <div>
    <button @click="siwe.login">
      Login
    </button>

    <button @click="siwe.clear">
      Logout
    </button>
  </div>
</template>

ic-siwe-js: v0.2.2

16 Jan 20:45

Choose a tag to compare

Added

  • Support for vanilla JS/TS projects. This should mean ic-siwe-js is usable with little to no headache in Svelte, Solid.JS and Lit. Vue still needs a custom submodule I believe.

Changed

  • Library renamed to ic-siwe-js and moved to the ic-siwe monorepo.
  • SiweIdentityProvider now requires only the canister id as a parameter.
  • React hook renamed from useSiweIdentity to useSiwe.
  • Project now uses xstate/store under the hood for state management instead of messy React Context.

Migration from v0.1.x

Replace dependency in package.json:

- "ic-use-siwe-identity": "^0.1.2",
+ "ic-siwe-js": "^0.2.2",

Import new name React hook from new location:

- import { useSiweIdentity } from "ic-use-siwe-identity";
+ import { useSiwe } from "ic-siwe-js/react";

Import SiweIdentityProvider from new location:

- import { SiweIdentityProvider } from "ic-use-siwe-identity";
+ import { SiweIdentityProvider } from "ic-siwe-js/react";

Use new simplified config for SiweIdentityProvider:

- <SiweIdentityProvider<_SERVICE>
-   canisterId={canisterId}
-   idlFactory={idlFactory}
- >
+ <SiweIdentityProvider canisterId={canisterId}>

v0.1.1

28 Aug 06:35
d0c5c4f

Choose a tag to compare

Changed

  • Updated dependencies: ic-cdk, upgrading from 0.15.0 to 0.15.1

v0.1.0 - Security fixes, making nonce required

22 Aug 13:30
30e31e8

Choose a tag to compare

Important

This release introduces breaking changes with new call signatures for the prepare_login and login functions.

This PR focuses on improving the security and reliability of the SIWE (Sign-In with Ethereum) process by ensuring proper cleanup of SIWE messages, implementing nonce-based security measures, and validating signature expiration. These changes help prevent replay attacks and ensure that expired signatures are not accepted.

Key Changes

  • Ensure Expired SIWE Messages Removal: Added logic to remove SIWE messages on failed login attempts to prevent stale data retention.
  • Nonce Generation for SIWE Messages: Implemented nonce generation for SIWE messages to enhance security by preventing replay attacks.
  • Signature Expiry Validation: Added functionality to return an error if a signature has expired.

Detailed Changes

Commits

  1. 6daf4563f95f4dc653cb717f053e45e2fed578b9:
    • Fix: Remove stored SIWE message on failed login attempts.
  2. 0b1118b822201b5bb124cfc0bd505a3c9550e29a:
    • Feature: Secure generated SIWE messages using a nonce.
  3. c4cd84dc3125408100e3f37a1138e4a4cd3b5c2d:
    • Fix: Return error if signature has expired.

Detailed Code Changes

  • New Functionality:

    • Added is_expired function in SignatureMap to check if a signature has expired:
      pub fn is_expired(&self, now: u64, seed_hash: Hash, delegation_hash: Hash) -> bool {
          let expiration = self
              .expiration_queue
              .iter()
              .find(|e| e.seed_hash == seed_hash && e.delegation_hash == delegation_hash);
          if let Some(expiration) = expiration {
              return now > expiration.signature_expires_at;
          }
          false
      }
    • Modified login function to remove SIWE message on failed login attempts:
      match recover_eth_address(&message_string, signature) {
          Ok(recovered_address) => {
              if recovered_address != address.as_str() {
                  siwe_messages.remove(address, nonce);
                  return Err(LoginError::AddressMismatch);
              }
          }
          Err(e) => {
              siwe_messages.remove(address, nonce);
              return Err(LoginError::EthError(e));
          }
      };
  • Nonce Implementation:

    • Updated prepare_login to generate and include a nonce:
      pub fn prepare_login(address: &EthAddress) -> Result<(SiweMessage, String), EthError> {
          let nonce = generate_nonce();
          let message = SiweMessage::new(address, &nonce);
          SIWE_MESSAGES.with_borrow_mut(|siwe_messages| {
              siwe_messages.insert(message.clone(), address, &nonce);
          });
          Ok((message, nonce))
      }
  • Signature Expiry Validation:

    • Added signature expiry validation in witness function:
      pub fn witness(
          seed: Hash,
          delegation_hash: Hash,
      ) -> Result<HashTree, DelegationError> {
          let seed_hash = hash::hash_bytes(seed);
          if signature_map.is_expired(get_current_time(), seed_hash, delegation_hash) {
              return Err(DelegationError::SignatureExpired);
          }
          let witness = signature_map
              .witness(seed_hash, delegation_hash)
              .ok_or(DelegationError::SignatureNotFound)?;
          Ok(witness)
      }

v0.0.7

05 Jul 13:54
7072092

Choose a tag to compare

ic_siwe

Changed

  • Updated dependencies: candid, ic-cdk, ic-cdk-timers

ic_siwe_provider

Changed

  • Updated dependencies: candid, ic-cdk, ic-stable-structures

v0.0.6

25 Mar 11:29
fd431f2

Choose a tag to compare

What's Changed

  • Add/runtime feature IncludeUriInSeed by @kristoferlund in #5
  • Add/runtime feature DisableEthToPrincipalMapping and DisablePrincipalToEthMapping by @kristoferlund in #6

Runtime Features

The runtime behaviour of the ic_siwe_provider canister and the ic_siwe library can be customized using the following settings:

IncludeUriInSeed

Default: URI is not included in the seed

When set, the URI is included in the seed used to generate the principal. Including the URI in the seed does not add any additional security in a scenario where ic_siwe_provider is deployed and configured to serve only one domain. However, if the ic_siwe library is used in a custom canister, that delagetes identities for more than one domain, it is recommended to enable this feature to ensure that the principal is unique for each domain.

  runtime_features = opt vec { \
    variant { IncludeUriInSeed } \
  }; 

DisableEthToPrincipalMapping

Default: Mapping is enabled

When set, the mapping of Ethereum addresses to Principals is disabled. This also disables the canister endpoints get_principal.

  runtime_features = opt vec { \
    variant { DisableEthToPrincipalMapping } \
  }; 

DisablePrincipalToEthMapping

Default: Mapping is enabled

When set, the mapping of Principals to Ethereum addresses is disabled. This also disables the canister endpoints get_address and get_caller_address.

  runtime_features = opt vec { \
    variant { DisablePrincipalToEthMapping } \
  }; 

v0.0.10, ic-use-siwe-identity

18 Mar 20:56

Choose a tag to compare

Changed

  • The login function now returns a Promise that resolves to the Identity of the logged in user. New signature: login: () => Promise<DelegationIdentity | undefined>.
  • Upgraded wagmi to v2.5.7.
    • This introduces TanStack Query as an additional dependency.
    • Also, this means the signture for signMessageStatus has changed slightly to signMessageStatus: "error" | "idle" | "pending" | "success".
  • Upgraded viem to v2.8.4

v0.0.9, ic-use-siwe-identity

07 Mar 10:54

Choose a tag to compare

Changed

  • Moved @dfinity/xxx dependencies from dependencies to peerDependencies to reduce package size.

v0.0.5

22 Feb 21:57

Choose a tag to compare

ic_siwe_provider

Fixed

  • Pre-built provider canister did not include metadata, now fixed.

v0.0.4

31 Jan 10:30

Choose a tag to compare

ic_siwe

Aligning version numbers with ic_siwe_provider

Added

  • EthAddress and EthSignature structs for type safety.
  • Added basic validation of delegation targets. Duplicate targets are now rejected.

Changed

  • Library functions now mostly returns custom error types instead of strings. As a result, many error messages now differ slighlty to previous version.
  • prepare_login and login now requires EthAddress and EthSignature structs instead of strings.
  • Replaced create_user_canister_pubkey with a more readable implementation.

ic_siwe_provider

Changed

  • Service functions prepare_login, login and get_delegation have been renamed siwe_prepare_login, siwe_login and siwe_get_delegation respectively. See ic_siwe_provider.did for details.