aboutsummaryrefslogtreecommitdiff
path: root/azalea-client/src
diff options
context:
space:
mode:
authormat <27899617+mat-1@users.noreply.github.com>2022-10-16 22:54:54 -0500
committerGitHub <noreply@github.com>2022-10-16 22:54:54 -0500
commit4cef62e8e4aa04e44048eb67e5091c12a73d2a09 (patch)
tree1c3b03bad262bdcab878cd42d445676290000bea /azalea-client/src
parent993914d175609e5d291e7caafc1983379642e7fe (diff)
downloadazalea-drasl-4cef62e8e4aa04e44048eb67e5091c12a73d2a09.tar.xz
Microsoft Authentication (#29)
* a * try to do more work on auth signing (untested) * well auth works when i remove the d= so * auth stuff * sessionserver stuff * add auth in azalea-protocol/client * caching* refreshing microsoft auth tokens isn't implemented yet, also i haven't tested it * how did i not notice that i had the code duplicated * fix cache * add refreshing msa token * replace some printlns with log::trace * auth works! * Update main.rs * fix clippy warnings
Diffstat (limited to 'azalea-client/src')
-rw-r--r--azalea-client/src/account.rs27
-rw-r--r--azalea-client/src/client.rs18
-rw-r--r--azalea-client/src/get_mc_dir.rs34
-rwxr-xr-xazalea-client/src/lib.rs1
4 files changed, 76 insertions, 4 deletions
diff --git a/azalea-client/src/account.rs b/azalea-client/src/account.rs
index c554908f..94e84ab8 100644
--- a/azalea-client/src/account.rs
+++ b/azalea-client/src/account.rs
@@ -1,20 +1,45 @@
//! Connect to Minecraft servers.
-use crate::{client::JoinError, Client, Event};
+use crate::{client::JoinError, get_mc_dir, Client, Event};
use azalea_protocol::ServerAddress;
use tokio::sync::mpsc::UnboundedReceiver;
+use uuid::Uuid;
/// Something that can join Minecraft servers.
pub struct Account {
pub username: String,
+ /// The access token for authentication. You can obtain one of these
+ /// manually from azalea-auth.
+ pub access_token: Option<String>,
+ /// Only required for online-mode accounts.
+ pub uuid: Option<uuid::Uuid>,
}
impl Account {
pub fn offline(username: &str) -> Self {
Self {
username: username.to_string(),
+ access_token: None,
+ uuid: None,
}
}
+ pub async fn microsoft(email: &str) -> Result<Self, azalea_auth::AuthError> {
+ let minecraft_dir = get_mc_dir::minecraft_dir().unwrap();
+ let auth_result = azalea_auth::auth(
+ email,
+ azalea_auth::AuthOpts {
+ cache_file: Some(minecraft_dir.join("azalea-auth.json")),
+ ..Default::default()
+ },
+ )
+ .await?;
+ Ok(Self {
+ username: auth_result.profile.name,
+ access_token: Some(auth_result.access_token),
+ uuid: Some(Uuid::parse_str(&auth_result.profile.id).expect("Invalid UUID")),
+ })
+ }
+
/// Joins the Minecraft server on the given address using this account.
pub async fn join(
&self,
diff --git a/azalea-client/src/client.rs b/azalea-client/src/client.rs
index 09f68c4a..25c68c5d 100644
--- a/azalea-client/src/client.rs
+++ b/azalea-client/src/client.rs
@@ -38,7 +38,6 @@ use std::{
};
use thiserror::Error;
use tokio::{
- io::AsyncWriteExt,
sync::mpsc::{self, UnboundedReceiver, UnboundedSender},
task::JoinHandle,
time::{self},
@@ -105,6 +104,8 @@ pub enum JoinError {
ReadPacket(#[from] azalea_protocol::read::ReadPacketError),
#[error("{0}")]
Io(#[from] io::Error),
+ #[error("{0}")]
+ SessionServer(#[from] azalea_auth::sessionserver::SessionServerError),
}
#[derive(Error, Debug)]
@@ -159,7 +160,17 @@ impl Client {
debug!("Got encryption request");
let e = azalea_crypto::encrypt(&p.public_key, &p.nonce).unwrap();
- // TODO: authenticate with the server here (authenticateServer)
+ if let Some(access_token) = &account.access_token {
+ conn.authenticate(
+ access_token,
+ &account
+ .uuid
+ .expect("Uuid must be present if access token is present."),
+ e.secret_key,
+ p,
+ )
+ .await?;
+ }
conn.write(
ServerboundKeyPacket {
@@ -171,6 +182,7 @@ impl Client {
.get(),
)
.await?;
+
conn.set_encryption_key(e.secret_key);
}
ClientboundLoginPacket::LoginCompression(p) => {
@@ -237,7 +249,7 @@ impl Client {
/// Disconnect from the server, ending all tasks.
pub async fn shutdown(self) -> Result<(), std::io::Error> {
- self.write_conn.lock().await.write_stream.shutdown().await?;
+ self.write_conn.lock().await.shutdown().await?;
let tasks = self.tasks.lock();
for task in tasks.iter() {
task.abort();
diff --git a/azalea-client/src/get_mc_dir.rs b/azalea-client/src/get_mc_dir.rs
new file mode 100644
index 00000000..abc5b3c8
--- /dev/null
+++ b/azalea-client/src/get_mc_dir.rs
@@ -0,0 +1,34 @@
+//! Find out where the user's .minecraft directory is.
+//!
+//! Used for the auth cache.
+
+use std::path::PathBuf;
+
+/// Return the location of the user's .minecraft directory.
+///
+/// Windows: `%appdata%\.minecraft`\
+/// Mac: `$HOME/Library/Application Support/minecraft`\
+/// Linux: `$HOME/.minecraft`
+///
+/// Anywhere else it'll return None.
+pub fn minecraft_dir() -> Option<PathBuf> {
+ #[cfg(target_os = "windows")]
+ {
+ let appdata = std::env::var("APPDATA").ok()?;
+ Some(PathBuf::from(appdata).join(".minecraft"))
+ }
+ #[cfg(target_os = "macos")]
+ {
+ let home = std::env::var("HOME").ok()?;
+ Some(PathBuf::from(home).join("Library/Application Support/minecraft"))
+ }
+ #[cfg(target_os = "linux")]
+ {
+ let home = std::env::var("HOME").ok()?;
+ Some(PathBuf::from(home).join(".minecraft"))
+ }
+ #[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
+ {
+ None
+ }
+}
diff --git a/azalea-client/src/lib.rs b/azalea-client/src/lib.rs
index a918ca32..c30ca103 100755
--- a/azalea-client/src/lib.rs
+++ b/azalea-client/src/lib.rs
@@ -2,6 +2,7 @@
mod account;
mod client;
+mod get_mc_dir;
mod movement;
pub mod ping;
mod player;