Skip to main content

aws_cognito_srp/
lib.rs

1#![crate_name = "aws_cognito_srp"]
2#![deny(missing_docs)]
3#![deny(clippy::all)]
4#![warn(clippy::pedantic)]
5#![warn(clippy::nursery)]
6#![warn(missing_debug_implementations, rust_2018_idioms, rustdoc::all)]
7#![allow(rustdoc::private_doc_tests)]
8#![forbid(unsafe_code)]
9
10//! # AWS Cognito SRP
11//!
12//! A Rust implementation of the Secure Remote Password (SRP) protocol for AWS Cognito.
13//!
14//! This includes helpers for **User** (`USER_SRP_AUTH` / `PASSWORD_VERIFIER`) and **Device** (`DEVICE_SRP_AUTH` / `DEVICE_PASSWORD_VERIFIER`) authentication flows, as
15//! well as the `ConfirmDevice` flow.
16//!
17//! ## Usage
18//!
19//! ```toml
20//! [dependencies]
21//! aws-cognito-srp = "0.2.3"
22//! ```
23//!
24//! ### User authentication
25//!
26//! The [authentication flow](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-authentication-flow-methods.html#Built-in-authentication-flow-and-challenges)
27//! is described in detail the AWS Cognito documentation.
28//!
29//! When performing the SRP authentication flow, the correct parameters can be generated for the [InitiateAuth](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_InitiateAuth.html) request, when using the
30//! `USER_SRP_AUTH` flow type, and the subsequent [RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html) request when the `PASSWORD_VERIFIER` challenge is
31//! issued.
32//!
33//! ```no_run
34//! use aws_cognito_srp::{UserAuthenticationParameters, SrpClient, SrpError, User, VerificationParameters};
35//!
36//! let client_id = "";
37//!
38//! // Optional: If your App client is configured with a client secret, AWS Cognito will require that
39//! // a secret is provided during the authentication flow (which requires the client secret).
40//! //
41//! // If your App client does not have a client secret, you can omit this parameter.
42//! //
43//! // https://docs.aws.amazon.com/cognito/latest/developerguide/signing-up-users-in-your-app.html#cognito-user-pools-computing-secret-hash
44//! let client_secret = Some("");
45//!
46//! let user = User::new(
47//!      // The ID of the AWS Cognito User Pool the user is registered with.
48//!      "<pool id>",
49//!
50//!      // The credentials of the user.
51//!      "<username>",
52//!      "<password>"
53//! );
54//!
55//! let client = SrpClient::new(user, client_id, client_secret);
56//!
57//! // Part 1: Generate the auth parameters for the initial `InitiateAuth` request
58//! let UserAuthenticationParameters {
59//!     a, // SRP_A
60//!     username, // USERNAME
61//! } = client.get_auth_parameters();
62//!
63//! let secret_hash = client.get_secret_hash(); // SECRET_HASH (if required)
64//!
65//! // Part 2: Generate the challenge response parameters for the `PASSWORD_VERIFIER` challenge issued
66//! // by Cognito in response to the `InitiateAuth` request.
67//! let VerificationParameters {
68//!     password_claim_secret_block, // PASSWORD_CLAIM_SECRET_BLOCK
69//!     password_claim_signature, // PASSWORD_CLAIM_SIGNATURE
70//!     timestamp // TIMESTAMP
71//! } = client.verify(
72//!     "SECRET_BLOCK_FROM_INITIATE_AUTH_RESPONSE",
73//!     "USER_ID_FOR_SRP_FROM_INITIATE_AUTH_RESPONSE",
74//!     "SALT_FROM_INITIATE_AUTH_RESPONSE",
75//!     "SRP_B_FROM_INITIATE_AUTH_RESPONSE"
76//! )?;
77//!
78//! # Ok::<(), SrpError>(())
79//! ```
80//!
81//! ### Device authentication
82//!
83//! The [authentication flow](https://docs.aws.amazon.com/cognito/latest/developerguide/amazon-cognito-user-pools-authentication-flow-methods.html#Built-in-authentication-flow-and-challenges)
84//! is described in detail the AWS Cognito documentation.
85//!
86//! When performing the SRP authentication flow, if a `DEVICE_KEY` is provided, AWS Cognito will prompt for device authentication.
87//!
88//! The correct SRP parameters can be generated for the two [RespondToAuthChallenge](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_RespondToAuthChallenge.html) requests needed when the `DEVICE_SRP_AUTH` and
89//! `DEVICE_PASSWORD_VERIFIER` challenges are issued.
90//!
91//! ```no_run
92//! use aws_cognito_srp::{DeviceAuthenticationParameters, TrackedDevice, SrpClient, SrpError, User, VerificationParameters};
93//!
94//! let client_id = "";
95//!
96//! // Optional: If your App client is configured with a client secret, AWS Cognito will require that
97//! // a secret is provided during the authentication flow (which requires the client secret).
98//! //
99//! // If your App client does not have a client secret, you can omit this parameter.
100//! //
101//! // https://docs.aws.amazon.com/cognito/latest/developerguide/signing-up-users-in-your-app.html#cognito-user-pools-computing-secret-hash
102//! let client_secret = Some("");
103//!
104//! let tracked_device = TrackedDevice::new(
105//!      // The ID of the AWS Cognito User Pool the user is registered with.
106//!      "<pool id>",
107//!
108//!      // The tracked device.
109//!      "<device group key>",
110//!      "<device key>",
111//!      "<device password>"
112//! );
113//!
114//! let client = SrpClient::new(tracked_device, client_id, client_secret);
115//!
116//! // Part 1: Generate the challenge response parameters for the `RespondToAuthChallenge` request
117//! // when responding to the `DeviceSrpAuth` challenge issued by AWS Cognito.
118//! let DeviceAuthenticationParameters {
119//!     a, // SRP_A
120//!     device_key // DEVICE_KEY
121//! } = client.get_auth_parameters();
122//!
123//! let secret_hash = client.get_secret_hash("<username of the owner of the tracked device>"); // SECRET_HASH (if required)
124//!
125//! // Part 2: Generate the challenge response parameters for the `DEVICE_PASSWORD_VERIFIER` challenge
126//! // issued by AWS Cognito in response to the `RespondToAuthChallenge` request.
127//! let VerificationParameters {
128//!     password_claim_secret_block, // PASSWORD_CLAIM_SECRET_BLOCK
129//!     password_claim_signature, // PASSWORD_CLAIM_SIGNATURE
130//!     timestamp // TIMESTAMP
131//! } = client.verify(
132//!     "SECRET_BLOCK_FROM_INITIATE_AUTH_RESPONSE",
133//!     "SALT_FROM_INITIATE_AUTH_RESPONSE",
134//!     "SRP_B_FROM_INITIATE_AUTH_RESPONSE"
135//! )?;
136//!
137//! # Ok::<(), SrpError>(())
138//! ```
139//!
140//! ### Confirm device
141//!
142//! Once a user has been authenticated, if the User Pool is configured to allow device tracking, a
143//! [ConfirmDevice](https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_ConfirmDevice.html) request can be made.
144//!
145//! This request passes in a verifier and salt for a random password generated for the untracked device. And, once confirmed, subsequent logins can use
146//! [device authentication flow](#device-authentication), citing the device key, along with the random password generated here.
147//!
148//! ```
149//! use aws_cognito_srp::{TrackedDevice, PasswordVerifierParameters, SrpClient, SrpError, User, UntrackedDevice};
150//!
151//! let client_id = "";
152//!
153//! // Optional: If your App client is configured with a client secret, AWS Cognito will require that
154//! // a secret is provided during the authentication flow (which requires the client secret).
155//! //
156//! // If your App client does not have a client secret, you can omit this parameter.
157//! //
158//! // https://docs.aws.amazon.com/cognito/latest/developerguide/signing-up-users-in-your-app.html#cognito-user-pools-computing-secret-hash
159//! let client_secret = Some("");
160//!
161//! let untracked_device = UntrackedDevice::new(
162//!      // The ID of the AWS Cognito User Pool the user is registered with.
163//!      "<pool id>",
164//!
165//!      // The device to be tracked.
166//!      "<device group key>",
167//!      "<device key>"
168//! );
169//!
170//! let client = SrpClient::new(untracked_device, client_id, client_secret);
171//!
172//! // Part 1: Generate a password, and the verifier parameters (verifier and salt) for the `ConfirmDevice`
173//! // request.
174//! let PasswordVerifierParameters {
175//!     verifier, // PasswordVerifier
176//!     salt, // Salt
177//!     password // The devices password (should be stored to use with device authentication later)
178//! } = client.get_password_verifier();
179//!
180//! // Part 2: Once the `ConfirmDevice` request has succeeded, the untracked device can then be converted
181//! // into a tracked device, which can be used for Device authentication later.
182//! let tracked_device = client.take_credentials()
183//!     .into_tracked(&password);
184//!
185//! # Ok::<(), SrpError>(())
186//! ```
187//!
188//! ## Contributing
189//!
190//! Many of the tests require that an AWS Cognito User Pool, configured with SRP authentication and device
191//! tracking, be available to act as a mock server.
192//!
193//! The setup of a suitable User Pool is fully automated with Terraform (see the [`infrastructure`](infrastructure/) folder).
194//!
195//! ### Set up
196//!
197//! In order to setup the test environment, Terraform needs to be installed and AWS credentials need to be
198//! configured locally.
199//!
200//! Once this is done, running `apply` should setup the Terraform backend, and the user pool and app client in the correct state:
201//! ```sh
202//! # Setup state backend
203//! cd infrastructure/state && terraform init && terraform apply
204//!
205//! # Setup user pool
206//! cd infrastructure/tests && terraform init --backend-config="./local.config" && terraform apply
207//! ```
208//!
209//! After the user pool is set up, multiple environment variables need to be set in a `.env` file.
210//!
211//! The `.env` file can be created by using `.env.example` as a template:
212//! ```sh
213//! cp .env.example .env
214//! ```
215//!
216//! ### Running tests
217//!
218//! The tests can be run with:
219//! ```sh
220//! cargo test
221//! ```
222//!
223//! ### Tear down
224//!
225//! The test environment can be torn down at any point with:
226//! ```sh
227//! cd infrastructure/tests && terraform destroy
228//! ```
229
230#[macro_use]
231extern crate lazy_static;
232
233pub use crate::client::{Credentials, SrpClient, TrackedDevice, UntrackedDevice, User};
234pub use crate::client::{
235    DeviceAuthenticationParameters, PasswordVerifierParameters, UserAuthenticationParameters,
236    VerificationParameters,
237};
238pub use crate::error::SrpError;
239
240mod client;
241mod constant;
242mod error;