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

Login and secret storage in Enarx CLI #194

Closed
rvolosatovs opened this issue Jun 20, 2022 · 1 comment
Closed

Login and secret storage in Enarx CLI #194

rvolosatovs opened this issue Jun 20, 2022 · 1 comment
Assignees

Comments

@rvolosatovs
Copy link
Member

rvolosatovs commented Jun 20, 2022

The flow should be as follows:

  1. CLI constructs an OpenID Client, performs discovery on issuer URL and constructs an auth URL with a redirect to localhost:$PORT
  2. CLI prints the URL to stdout and listens on localhost:$PORT (meanwhile the user opens the URL on the same machine the CLI is running on and performs the login)
  3. Once the request arrives on the socket after successful login, code parameter should be extracted from the URL and a request should be made to identity provider to exchange the code to an access token.
  4. Token is stored to disk or in the OS keychain

Very rough, insecure example adapted from https://docs.rs/openidconnect/2.3.1/openidconnect/index.html#getting-started-authorization-code-grant-w-pkce:

    let provider_metadata =
        CoreProviderMetadata::discover(&IssuerUrl::new(oidc_issuer.into())?, http_client)?;

    let oidc_secret = oidc_secret.unwrap();

    let client = CoreClient::from_provider_metadata(
        provider_metadata.clone(),
        ClientId::new(<client_id>),
        Some(ClientSecret::new(<client_secret>)),
    )
    .set_redirect_uri(RedirectUrl::new("http://127.0.0.1:8081".to_string())?);

    let (pkce_challenge, pkce_verifier) = PkceCodeChallenge::new_random_sha256();

    let (auth_url, _csrf_token, nonce) = client
        .authorize_url(
            CoreAuthenticationFlow::AuthorizationCode,
            CsrfToken::new_random,
            Nonce::new_random,
        )
        .add_scope(Scope::new("read".to_string()))
        .add_scope(Scope::new("write".to_string()))
        .url();

    println!("Browse to: {}", auth_url);

    let (stream, _) = TcpListener::bind("127.0.0.1:8081").await?.accept().await?;
    Http::new()
        .serve_connection(
            stream.compat(),
            service_fn(|req| async move {
                let provider_metadata = CoreProviderMetadata::discover(
                    &IssuerUrl::new("<issuer_url>".to_string()).unwrap(),
                    http_client,
                )
                .unwrap();

                let client = CoreClient::from_provider_metadata(
                    provider_metadata,
                    ClientId::new(<client_id>),
                    Some(ClientSecret::new(<client_secret>)),
                )
                .set_redirect_uri(RedirectUrl::new("http://127.0.0.1:8081".to_string()).unwrap());

                let uri = req.uri();
                let query = uri.path_and_query().unwrap().query().unwrap();

                let params = query.split('&').collect::<Vec<&str>>();
                let code = params
                    .iter()
                    .find(|p| p.starts_with("code="))
                    .unwrap()
                    .trim_start_matches("code=");

                let token_response = client
                    .exchange_code(AuthorizationCode::new(code.to_string()))
                    .request(http_client)
                    .unwrap();

                let access_token = token_response.access_token();

                println!("Token: {}", access_token.secret());
                Ok::<_, Infallible>(Response::new(Body::from("received token")))
            }),
        )
        .await
        .context("failed to handle request")
        .unwrap();

Refs #191
Refs #118
enarx/enarx#1953

Some of the session-related code from https://github.com/profianinc/benefice/tree/main/crates/auth could be extracted and adapted to OpenID Conect client login flow.

@rvolosatovs rvolosatovs changed the title Extract crate/auth redirect and secret storage code into Enarx CLI Login and secret storage code in Enarx CLI Jun 23, 2022
@rvolosatovs rvolosatovs changed the title Login and secret storage code in Enarx CLI Login and secret storage in Enarx CLI Jun 23, 2022
@rvolosatovs
Copy link
Member Author

Turned out we can use device flow for this, see https://github.com/rvolosatovs/oidc-login for a working example

@platten platten closed this as completed Jul 6, 2022
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

No branches or pull requests

4 participants