-
Notifications
You must be signed in to change notification settings - Fork 6
feat: Login with Internet Identity #495
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
Merged
Merged
Changes from 8 commits
Commits
Show all changes
25 commits
Select commit
Hold shift + click to select a range
5adbeb3
initial impl
adamspofford-dfinity 592c7b5
fix canister signature code
adamspofford-dfinity a97a46e
Shortcode flow
adamspofford-dfinity 447dcd5
mv
adamspofford-dfinity 8d73890
Automatically open the URL
adamspofford-dfinity 961cb7a
Switch to keyring storage
adamspofford-dfinity 615130d
New flow and fixed mainnet canister
adamspofford-dfinity 543a252
Add storage mode parameter
adamspofford-dfinity fdbc4e7
Add .well-known record and host param
adamspofford-dfinity a15ce47
clippy
adamspofford-dfinity 605d923
move out of operations module
adamspofford-dfinity e3f2117
fix lockfile
adamspofford-dfinity 390b651
hide commands for beta release and use final domain
adamspofford-dfinity 8c4b7d6
accept domains without scheme
adamspofford-dfinity 5a3f3fb
Check for duplicate name before beginning
adamspofford-dfinity f6738e3
audit
adamspofford-dfinity 0c23c62
stuff
adamspofford-dfinity 3ed7c68
lint
adamspofford-dfinity 1dc6bd6
artefact of earlier design
adamspofford-dfinity be083b3
bump ic-agent
adamspofford-dfinity 0f63184
Merge branch 'main' into spofford/ii-login-poc
adamspofford-dfinity 735861d
[copilot] unit tests for to_agent_types
adamspofford-dfinity 1ec57ee
fix copilot hallucinations
adamspofford-dfinity ab38aac
validate password
adamspofford-dfinity 620d85c
DRY pem parse
adamspofford-dfinity File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,106 @@ | ||
| use clap::Args; | ||
| use dialoguer::Password; | ||
| use elliptic_curve::zeroize::Zeroizing; | ||
| use ic_agent::{Identity as _, export::Principal, identity::BasicIdentity}; | ||
| use icp::{context::Context, fs::read_to_string, identity::key, prelude::*}; | ||
| use snafu::{ResultExt, Snafu}; | ||
| use tracing::{info, warn}; | ||
|
|
||
| use crate::{commands::identity::StorageMode, operations::ii_poll}; | ||
|
|
||
| /// Link an Internet Identity to a new identity | ||
| #[derive(Debug, Args)] | ||
| pub(crate) struct IiArgs { | ||
| /// Name for the linked identity | ||
| name: String, | ||
|
|
||
| /// Where to store the session private key | ||
| #[arg(long, value_enum, default_value_t)] | ||
| storage: StorageMode, | ||
|
|
||
|
adamspofford-dfinity marked this conversation as resolved.
|
||
| /// Read the storage password from a file instead of prompting (for --storage password) | ||
| #[arg(long, value_name = "FILE")] | ||
| storage_password_file: Option<PathBuf>, | ||
| } | ||
|
|
||
| pub(crate) async fn exec(ctx: &Context, args: &IiArgs) -> Result<(), IiError> { | ||
| let create_format = match args.storage { | ||
| StorageMode::Plaintext => key::CreateFormat::Plaintext, | ||
| StorageMode::Keyring => key::CreateFormat::Keyring, | ||
| StorageMode::Password => { | ||
| let password = if let Some(path) = &args.storage_password_file { | ||
| read_to_string(path) | ||
| .context(ReadStoragePasswordFileSnafu)? | ||
| .trim() | ||
| .to_string() | ||
| } else { | ||
| Password::new() | ||
| .with_prompt("Enter password to encrypt identity") | ||
| .with_confirmation("Confirm password", "Passwords do not match") | ||
| .interact() | ||
| .context(StoragePasswordTermReadSnafu)? | ||
| }; | ||
| key::CreateFormat::Pbes2 { | ||
| password: Zeroizing::new(password), | ||
| } | ||
| } | ||
|
adamspofford-dfinity marked this conversation as resolved.
|
||
| }; | ||
|
|
||
| let secret_key = ic_ed25519::PrivateKey::generate(); | ||
| let identity_key = key::IdentityKey::Ed25519(secret_key.clone()); | ||
| let basic = BasicIdentity::from_raw_key(&secret_key.serialize_raw()); | ||
| let der_public_key = basic.public_key().expect("ed25519 always has a public key"); | ||
|
|
||
| let chain = ii_poll::poll_for_delegation(&der_public_key) | ||
| .await | ||
| .context(PollSnafu)?; | ||
|
|
||
| let from_key = hex::decode(&chain.public_key).context(DecodeFromKeySnafu)?; | ||
| let ii_principal = Principal::self_authenticating(&from_key); | ||
|
|
||
| ctx.dirs | ||
| .identity()? | ||
| .with_write(async |dirs| { | ||
| key::link_ii_identity( | ||
| dirs, | ||
| &args.name, | ||
| identity_key, | ||
| &chain, | ||
| ii_principal, | ||
| create_format, | ||
| ) | ||
| }) | ||
| .await? | ||
| .context(LinkSnafu)?; | ||
|
|
||
| info!("Identity `{}` linked to Internet Identity", args.name); | ||
|
|
||
| if matches!(args.storage, StorageMode::Plaintext) { | ||
| warn!( | ||
| "This identity is stored in plaintext and is not secure. Do not use it for anything of significant value." | ||
| ); | ||
| } | ||
|
|
||
| Ok(()) | ||
| } | ||
|
|
||
| #[derive(Debug, Snafu)] | ||
| pub(crate) enum IiError { | ||
| #[snafu(display("failed to read storage password file"))] | ||
| ReadStoragePasswordFile { source: icp::fs::IoError }, | ||
|
|
||
| #[snafu(display("failed to read storage password from terminal"))] | ||
| StoragePasswordTermRead { source: dialoguer::Error }, | ||
|
|
||
| #[snafu(display("failed during II authentication"))] | ||
| Poll { source: ii_poll::IiPollError }, | ||
|
|
||
| #[snafu(display("invalid public key in delegation chain"))] | ||
| DecodeFromKey { source: hex::FromHexError }, | ||
|
|
||
| #[snafu(transparent)] | ||
| LockIdentityDir { source: icp::fs::lock::LockError }, | ||
|
|
||
| #[snafu(display("failed to link II identity"))] | ||
| Link { source: key::LinkIiIdentityError }, | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,9 +1,11 @@ | ||
| use clap::Subcommand; | ||
|
|
||
| pub(crate) mod hsm; | ||
| pub(crate) mod ii; | ||
|
|
||
| /// Link an external key to a new identity | ||
| #[derive(Debug, Subcommand)] | ||
| pub(crate) enum Command { | ||
| Hsm(hsm::HsmArgs), | ||
| Ii(ii::IiArgs), | ||
| } |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.