Launcher Auth (#450)

* Launcher Auth

* Finish auth

* final fixes
This commit is contained in:
Geometrically
2023-08-04 23:38:34 -07:00
committed by GitHub
parent a35dd67b77
commit 47e28d24c8
38 changed files with 1200 additions and 477 deletions

View File

@@ -1,4 +1,6 @@
//! Authentication flow based on Hydra
use crate::config::MODRINTH_API_URL;
use crate::state::CredentialsStore;
use crate::util::fetch::{fetch_advanced, fetch_json, FetchSemaphore};
use async_tungstenite as ws;
use chrono::{prelude::*, Duration};
@@ -10,7 +12,7 @@ use url::Url;
lazy_static! {
static ref HYDRA_URL: Url =
Url::parse("https://staging-api.modrinth.com/v2/auth/minecraft/")
Url::parse(&format!("{MODRINTH_API_URL}auth/minecraft/"))
.expect("Hydra URL parse failed");
}
@@ -40,7 +42,7 @@ struct TokenJSON {
token: String,
refresh_token: String,
expires_after: u32,
flow: String,
flow: Option<String>,
}
#[derive(Deserialize)]
@@ -68,7 +70,7 @@ pub struct HydraAuthFlow<S: AsyncRead + AsyncWrite + Unpin> {
impl HydraAuthFlow<ws::tokio::ConnectStream> {
pub async fn new() -> crate::Result<Self> {
let (socket, _) = ws::tokio::connect_async(
"wss://staging-api.modrinth.com/v2/auth/minecraft/ws",
"wss://api.modrinth.com/v2/auth/minecraft/ws",
)
.await?;
Ok(Self { socket })
@@ -96,7 +98,7 @@ impl HydraAuthFlow<ws::tokio::ConnectStream> {
pub async fn extract_credentials(
&mut self,
semaphore: &FetchSemaphore,
) -> crate::Result<Credentials> {
) -> crate::Result<(Credentials, Option<String>)> {
// Minecraft bearer token
let token_resp = self
.socket
@@ -117,14 +119,17 @@ impl HydraAuthFlow<ws::tokio::ConnectStream> {
let info = fetch_info(&token.token, semaphore).await?;
// Return structure from response
Ok(Credentials {
username: info.name,
id: info.id,
refresh_token: token.refresh_token,
access_token: token.token,
expires,
_ctor_scope: std::marker::PhantomData,
})
Ok((
Credentials {
username: info.name,
id: info.id,
refresh_token: token.refresh_token,
access_token: token.token,
expires,
_ctor_scope: std::marker::PhantomData,
},
token.flow,
))
}
}
@@ -134,10 +139,11 @@ pub async fn refresh_credentials(
) -> crate::Result<()> {
let resp = fetch_json::<TokenJSON>(
Method::POST,
"https://staging-api.modrinth.com/v2/auth/minecraft/refresh",
&format!("{MODRINTH_API_URL}auth/minecraft/refresh"),
None,
Some(serde_json::json!({ "refresh_token": credentials.refresh_token })),
semaphore,
&CredentialsStore(None),
)
.await?;
@@ -162,6 +168,7 @@ async fn fetch_info(
Some(("Authorization", &format!("Bearer {token}"))),
None,
semaphore,
&CredentialsStore(None),
)
.await?;
let value = serde_json::from_slice(&result)?;

View File

@@ -1,5 +1,6 @@
//! Downloader for Minecraft data
use crate::state::CredentialsStore;
use crate::{
event::{
emit::{emit_loading, loading_try_for_each_concurrent},
@@ -127,6 +128,7 @@ pub async fn download_client(
&client_download.url,
Some(&client_download.sha1),
&st.fetch_semaphore,
&CredentialsStore(None),
)
.await?;
write(&path, &bytes, &st.io_semaphore).await?;
@@ -206,7 +208,7 @@ pub async fn download_assets(
async {
if !resource_path.exists() {
let resource = fetch_cell
.get_or_try_init(|| fetch(&url, Some(hash), &st.fetch_semaphore))
.get_or_try_init(|| fetch(&url, Some(hash), &st.fetch_semaphore, &CredentialsStore(None)))
.await?;
write(&resource_path, resource, &st.io_semaphore).await?;
tracing::trace!("Fetched asset with hash {hash}");
@@ -216,7 +218,7 @@ pub async fn download_assets(
async {
if with_legacy {
let resource = fetch_cell
.get_or_try_init(|| fetch(&url, Some(hash), &st.fetch_semaphore))
.get_or_try_init(|| fetch(&url, Some(hash), &st.fetch_semaphore, &CredentialsStore(None)))
.await?;
let resource_path = st.directories.legacy_assets_dir().await.join(
name.replace('/', &String::from(std::path::MAIN_SEPARATOR))
@@ -273,7 +275,7 @@ pub async fn download_libraries(
artifact: Some(ref artifact),
..
}) => {
let bytes = fetch(&artifact.url, Some(&artifact.sha1), &st.fetch_semaphore)
let bytes = fetch(&artifact.url, Some(&artifact.sha1), &st.fetch_semaphore, &CredentialsStore(None))
.await?;
write(&path, &bytes, &st.io_semaphore).await?;
tracing::trace!("Fetched library {} to path {:?}", &library.name, &path);
@@ -288,7 +290,7 @@ pub async fn download_libraries(
&artifact_path
].concat();
let bytes = fetch(&url, None, &st.fetch_semaphore).await?;
let bytes = fetch(&url, None, &st.fetch_semaphore, &CredentialsStore(None)).await?;
write(&path, &bytes, &st.io_semaphore).await?;
tracing::trace!("Fetched library {} to path {:?}", &library.name, &path);
Ok::<_, crate::Error>(())
@@ -314,7 +316,7 @@ pub async fn download_libraries(
);
if let Some(native) = classifiers.get(&parsed_key) {
let data = fetch(&native.url, Some(&native.sha1), &st.fetch_semaphore).await?;
let data = fetch(&native.url, Some(&native.sha1), &st.fetch_semaphore, &CredentialsStore(None)).await?;
let reader = std::io::Cursor::new(&data);
if let Ok(mut archive) = zip::ZipArchive::new(reader) {
match archive.extract(st.directories.version_natives_dir(version).await) {