├── .gitignore ├── CODE_OF_CONDUCT.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── README.md └── src └── main.rs /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | .env 3 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | alinuxperson@gmail.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "anyhow" 7 | version = "1.0.44" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "61604a8f862e1d5c3229fdd78f8b02c68dcf73a4c4b05fd636d12240aaa242c1" 10 | 11 | [[package]] 12 | name = "autocfg" 13 | version = "1.0.1" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" 16 | 17 | [[package]] 18 | name = "base64" 19 | version = "0.13.0" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "904dfeac50f3cdaba28fc6f57fdcddb75f49ed61346676a78c4ffe55877802fd" 22 | 23 | [[package]] 24 | name = "bitflags" 25 | version = "1.3.2" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" 28 | 29 | [[package]] 30 | name = "block-buffer" 31 | version = "0.9.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "4152116fd6e9dadb291ae18fc1ec3575ed6d84c29642d97890f4b4a3417297e4" 34 | dependencies = [ 35 | "generic-array", 36 | ] 37 | 38 | [[package]] 39 | name = "buf_redux" 40 | version = "0.8.4" 41 | source = "registry+https://github.com/rust-lang/crates.io-index" 42 | checksum = "b953a6887648bb07a535631f2bc00fbdb2a2216f135552cb3f534ed136b9c07f" 43 | dependencies = [ 44 | "memchr", 45 | "safemem", 46 | ] 47 | 48 | [[package]] 49 | name = "bumpalo" 50 | version = "3.7.1" 51 | source = "registry+https://github.com/rust-lang/crates.io-index" 52 | checksum = "d9df67f7bf9ef8498769f994239c45613ef0c5899415fb58e9add412d2c1a538" 53 | 54 | [[package]] 55 | name = "byteorder" 56 | version = "1.4.3" 57 | source = "registry+https://github.com/rust-lang/crates.io-index" 58 | checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" 59 | 60 | [[package]] 61 | name = "bytes" 62 | version = "1.1.0" 63 | source = "registry+https://github.com/rust-lang/crates.io-index" 64 | checksum = "c4872d67bab6358e59559027aa3b9157c53d9358c51423c17554809a8858e0f8" 65 | 66 | [[package]] 67 | name = "cc" 68 | version = "1.0.70" 69 | source = "registry+https://github.com/rust-lang/crates.io-index" 70 | checksum = "d26a6ce4b6a484fa3edb70f7efa6fc430fd2b87285fe8b84304fd0936faa0dc0" 71 | 72 | [[package]] 73 | name = "cfg-if" 74 | version = "1.0.0" 75 | source = "registry+https://github.com/rust-lang/crates.io-index" 76 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 77 | 78 | [[package]] 79 | name = "core-foundation" 80 | version = "0.9.1" 81 | source = "registry+https://github.com/rust-lang/crates.io-index" 82 | checksum = "0a89e2ae426ea83155dccf10c0fa6b1463ef6d5fcb44cee0b224a408fa640a62" 83 | dependencies = [ 84 | "core-foundation-sys", 85 | "libc", 86 | ] 87 | 88 | [[package]] 89 | name = "core-foundation-sys" 90 | version = "0.8.2" 91 | source = "registry+https://github.com/rust-lang/crates.io-index" 92 | checksum = "ea221b5284a47e40033bf9b66f35f984ec0ea2931eb03505246cd27a963f981b" 93 | 94 | [[package]] 95 | name = "cpufeatures" 96 | version = "0.2.1" 97 | source = "registry+https://github.com/rust-lang/crates.io-index" 98 | checksum = "95059428f66df56b63431fdb4e1947ed2190586af5c5a8a8b71122bdf5a7f469" 99 | dependencies = [ 100 | "libc", 101 | ] 102 | 103 | [[package]] 104 | name = "digest" 105 | version = "0.9.0" 106 | source = "registry+https://github.com/rust-lang/crates.io-index" 107 | checksum = "d3dd60d1080a57a05ab032377049e0591415d2b31afd7028356dbf3cc6dcb066" 108 | dependencies = [ 109 | "generic-array", 110 | ] 111 | 112 | [[package]] 113 | name = "dotenv" 114 | version = "0.15.0" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" 117 | 118 | [[package]] 119 | name = "encoding_rs" 120 | version = "0.8.28" 121 | source = "registry+https://github.com/rust-lang/crates.io-index" 122 | checksum = "80df024fbc5ac80f87dfef0d9f5209a252f2a497f7f42944cff24d8253cac065" 123 | dependencies = [ 124 | "cfg-if", 125 | ] 126 | 127 | [[package]] 128 | name = "fnv" 129 | version = "1.0.7" 130 | source = "registry+https://github.com/rust-lang/crates.io-index" 131 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 132 | 133 | [[package]] 134 | name = "foreign-types" 135 | version = "0.3.2" 136 | source = "registry+https://github.com/rust-lang/crates.io-index" 137 | checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" 138 | dependencies = [ 139 | "foreign-types-shared", 140 | ] 141 | 142 | [[package]] 143 | name = "foreign-types-shared" 144 | version = "0.1.1" 145 | source = "registry+https://github.com/rust-lang/crates.io-index" 146 | checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" 147 | 148 | [[package]] 149 | name = "form_urlencoded" 150 | version = "1.0.1" 151 | source = "registry+https://github.com/rust-lang/crates.io-index" 152 | checksum = "5fc25a87fa4fd2094bffb06925852034d90a17f0d1e05197d4956d3555752191" 153 | dependencies = [ 154 | "matches", 155 | "percent-encoding", 156 | ] 157 | 158 | [[package]] 159 | name = "futures" 160 | version = "0.3.17" 161 | source = "registry+https://github.com/rust-lang/crates.io-index" 162 | checksum = "a12aa0eb539080d55c3f2d45a67c3b58b6b0773c1a3ca2dfec66d58c97fd66ca" 163 | dependencies = [ 164 | "futures-channel", 165 | "futures-core", 166 | "futures-io", 167 | "futures-sink", 168 | "futures-task", 169 | "futures-util", 170 | ] 171 | 172 | [[package]] 173 | name = "futures-channel" 174 | version = "0.3.17" 175 | source = "registry+https://github.com/rust-lang/crates.io-index" 176 | checksum = "5da6ba8c3bb3c165d3c7319fc1cc8304facf1fb8db99c5de877183c08a273888" 177 | dependencies = [ 178 | "futures-core", 179 | "futures-sink", 180 | ] 181 | 182 | [[package]] 183 | name = "futures-core" 184 | version = "0.3.17" 185 | source = "registry+https://github.com/rust-lang/crates.io-index" 186 | checksum = "88d1c26957f23603395cd326b0ffe64124b818f4449552f960d815cfba83a53d" 187 | 188 | [[package]] 189 | name = "futures-io" 190 | version = "0.3.17" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "522de2a0fe3e380f1bc577ba0474108faf3f6b18321dbf60b3b9c39a75073377" 193 | 194 | [[package]] 195 | name = "futures-sink" 196 | version = "0.3.17" 197 | source = "registry+https://github.com/rust-lang/crates.io-index" 198 | checksum = "36ea153c13024fe480590b3e3d4cad89a0cfacecc24577b68f86c6ced9c2bc11" 199 | 200 | [[package]] 201 | name = "futures-task" 202 | version = "0.3.17" 203 | source = "registry+https://github.com/rust-lang/crates.io-index" 204 | checksum = "1d3d00f4eddb73e498a54394f228cd55853bdf059259e8e7bc6e69d408892e99" 205 | 206 | [[package]] 207 | name = "futures-util" 208 | version = "0.3.17" 209 | source = "registry+https://github.com/rust-lang/crates.io-index" 210 | checksum = "36568465210a3a6ee45e1f165136d68671471a501e632e9a98d96872222b5481" 211 | dependencies = [ 212 | "autocfg", 213 | "futures-core", 214 | "futures-sink", 215 | "futures-task", 216 | "pin-project-lite", 217 | "pin-utils", 218 | "slab", 219 | ] 220 | 221 | [[package]] 222 | name = "generic-array" 223 | version = "0.14.4" 224 | source = "registry+https://github.com/rust-lang/crates.io-index" 225 | checksum = "501466ecc8a30d1d3b7fc9229b122b2ce8ed6e9d9223f1138d4babb253e51817" 226 | dependencies = [ 227 | "typenum", 228 | "version_check", 229 | ] 230 | 231 | [[package]] 232 | name = "getrandom" 233 | version = "0.1.16" 234 | source = "registry+https://github.com/rust-lang/crates.io-index" 235 | checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" 236 | dependencies = [ 237 | "cfg-if", 238 | "libc", 239 | "wasi 0.9.0+wasi-snapshot-preview1", 240 | ] 241 | 242 | [[package]] 243 | name = "getrandom" 244 | version = "0.2.3" 245 | source = "registry+https://github.com/rust-lang/crates.io-index" 246 | checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" 247 | dependencies = [ 248 | "cfg-if", 249 | "libc", 250 | "wasi 0.10.2+wasi-snapshot-preview1", 251 | ] 252 | 253 | [[package]] 254 | name = "h2" 255 | version = "0.3.5" 256 | source = "registry+https://github.com/rust-lang/crates.io-index" 257 | checksum = "3b21b78895ff1ade3f8df6a9a77917f20dc8b46d0069dd5a3837cf1f507a70ee" 258 | dependencies = [ 259 | "bytes", 260 | "fnv", 261 | "futures-core", 262 | "futures-sink", 263 | "futures-util", 264 | "http", 265 | "indexmap", 266 | "slab", 267 | "tokio", 268 | "tokio-util", 269 | "tracing", 270 | ] 271 | 272 | [[package]] 273 | name = "hashbrown" 274 | version = "0.11.2" 275 | source = "registry+https://github.com/rust-lang/crates.io-index" 276 | checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" 277 | 278 | [[package]] 279 | name = "headers" 280 | version = "0.3.4" 281 | source = "registry+https://github.com/rust-lang/crates.io-index" 282 | checksum = "f0b7591fb62902706ae8e7aaff416b1b0fa2c0fd0878b46dc13baa3712d8a855" 283 | dependencies = [ 284 | "base64", 285 | "bitflags", 286 | "bytes", 287 | "headers-core", 288 | "http", 289 | "mime", 290 | "sha-1", 291 | "time", 292 | ] 293 | 294 | [[package]] 295 | name = "headers-core" 296 | version = "0.2.0" 297 | source = "registry+https://github.com/rust-lang/crates.io-index" 298 | checksum = "e7f66481bfee273957b1f20485a4ff3362987f85b2c236580d81b4eb7a326429" 299 | dependencies = [ 300 | "http", 301 | ] 302 | 303 | [[package]] 304 | name = "hermit-abi" 305 | version = "0.1.19" 306 | source = "registry+https://github.com/rust-lang/crates.io-index" 307 | checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" 308 | dependencies = [ 309 | "libc", 310 | ] 311 | 312 | [[package]] 313 | name = "http" 314 | version = "0.2.5" 315 | source = "registry+https://github.com/rust-lang/crates.io-index" 316 | checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" 317 | dependencies = [ 318 | "bytes", 319 | "fnv", 320 | "itoa", 321 | ] 322 | 323 | [[package]] 324 | name = "http-body" 325 | version = "0.4.3" 326 | source = "registry+https://github.com/rust-lang/crates.io-index" 327 | checksum = "399c583b2979440c60be0821a6199eca73bc3c8dcd9d070d75ac726e2c6186e5" 328 | dependencies = [ 329 | "bytes", 330 | "http", 331 | "pin-project-lite", 332 | ] 333 | 334 | [[package]] 335 | name = "httparse" 336 | version = "1.5.1" 337 | source = "registry+https://github.com/rust-lang/crates.io-index" 338 | checksum = "acd94fdbe1d4ff688b67b04eee2e17bd50995534a61539e45adfefb45e5e5503" 339 | 340 | [[package]] 341 | name = "httpdate" 342 | version = "1.0.1" 343 | source = "registry+https://github.com/rust-lang/crates.io-index" 344 | checksum = "6456b8a6c8f33fee7d958fcd1b60d55b11940a79e63ae87013e6d22e26034440" 345 | 346 | [[package]] 347 | name = "hyper" 348 | version = "0.14.13" 349 | source = "registry+https://github.com/rust-lang/crates.io-index" 350 | checksum = "15d1cfb9e4f68655fa04c01f59edb405b6074a0f7118ea881e5026e4a1cd8593" 351 | dependencies = [ 352 | "bytes", 353 | "futures-channel", 354 | "futures-core", 355 | "futures-util", 356 | "h2", 357 | "http", 358 | "http-body", 359 | "httparse", 360 | "httpdate", 361 | "itoa", 362 | "pin-project-lite", 363 | "socket2", 364 | "tokio", 365 | "tower-service", 366 | "tracing", 367 | "want", 368 | ] 369 | 370 | [[package]] 371 | name = "hyper-tls" 372 | version = "0.5.0" 373 | source = "registry+https://github.com/rust-lang/crates.io-index" 374 | checksum = "d6183ddfa99b85da61a140bea0efc93fdf56ceaa041b37d553518030827f9905" 375 | dependencies = [ 376 | "bytes", 377 | "hyper", 378 | "native-tls", 379 | "tokio", 380 | "tokio-native-tls", 381 | ] 382 | 383 | [[package]] 384 | name = "idna" 385 | version = "0.2.3" 386 | source = "registry+https://github.com/rust-lang/crates.io-index" 387 | checksum = "418a0a6fab821475f634efe3ccc45c013f742efe03d853e8d3355d5cb850ecf8" 388 | dependencies = [ 389 | "matches", 390 | "unicode-bidi", 391 | "unicode-normalization", 392 | ] 393 | 394 | [[package]] 395 | name = "indexmap" 396 | version = "1.7.0" 397 | source = "registry+https://github.com/rust-lang/crates.io-index" 398 | checksum = "bc633605454125dec4b66843673f01c7df2b89479b32e0ed634e43a91cff62a5" 399 | dependencies = [ 400 | "autocfg", 401 | "hashbrown", 402 | ] 403 | 404 | [[package]] 405 | name = "input_buffer" 406 | version = "0.4.0" 407 | source = "registry+https://github.com/rust-lang/crates.io-index" 408 | checksum = "f97967975f448f1a7ddb12b0bc41069d09ed6a1c161a92687e057325db35d413" 409 | dependencies = [ 410 | "bytes", 411 | ] 412 | 413 | [[package]] 414 | name = "ipnet" 415 | version = "2.3.1" 416 | source = "registry+https://github.com/rust-lang/crates.io-index" 417 | checksum = "68f2d64f2edebec4ce84ad108148e67e1064789bee435edc5b60ad398714a3a9" 418 | 419 | [[package]] 420 | name = "itoa" 421 | version = "0.4.8" 422 | source = "registry+https://github.com/rust-lang/crates.io-index" 423 | checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" 424 | 425 | [[package]] 426 | name = "js-sys" 427 | version = "0.3.55" 428 | source = "registry+https://github.com/rust-lang/crates.io-index" 429 | checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" 430 | dependencies = [ 431 | "wasm-bindgen", 432 | ] 433 | 434 | [[package]] 435 | name = "lazy_static" 436 | version = "1.4.0" 437 | source = "registry+https://github.com/rust-lang/crates.io-index" 438 | checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" 439 | 440 | [[package]] 441 | name = "libc" 442 | version = "0.2.103" 443 | source = "registry+https://github.com/rust-lang/crates.io-index" 444 | checksum = "dd8f7255a17a627354f321ef0055d63b898c6fb27eff628af4d1b66b7331edf6" 445 | 446 | [[package]] 447 | name = "log" 448 | version = "0.4.14" 449 | source = "registry+https://github.com/rust-lang/crates.io-index" 450 | checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" 451 | dependencies = [ 452 | "cfg-if", 453 | ] 454 | 455 | [[package]] 456 | name = "matches" 457 | version = "0.1.9" 458 | source = "registry+https://github.com/rust-lang/crates.io-index" 459 | checksum = "a3e378b66a060d48947b590737b30a1be76706c8dd7b8ba0f2fe3989c68a853f" 460 | 461 | [[package]] 462 | name = "mcsoft-auth" 463 | version = "0.1.0" 464 | dependencies = [ 465 | "anyhow", 466 | "dotenv", 467 | "rand 0.8.4", 468 | "reqwest", 469 | "serde", 470 | "serde_json", 471 | "tokio", 472 | "warp", 473 | "webbrowser", 474 | ] 475 | 476 | [[package]] 477 | name = "memchr" 478 | version = "2.4.1" 479 | source = "registry+https://github.com/rust-lang/crates.io-index" 480 | checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" 481 | 482 | [[package]] 483 | name = "mime" 484 | version = "0.3.16" 485 | source = "registry+https://github.com/rust-lang/crates.io-index" 486 | checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" 487 | 488 | [[package]] 489 | name = "mime_guess" 490 | version = "2.0.3" 491 | source = "registry+https://github.com/rust-lang/crates.io-index" 492 | checksum = "2684d4c2e97d99848d30b324b00c8fcc7e5c897b7cbb5819b09e7c90e8baf212" 493 | dependencies = [ 494 | "mime", 495 | "unicase", 496 | ] 497 | 498 | [[package]] 499 | name = "mio" 500 | version = "0.7.13" 501 | source = "registry+https://github.com/rust-lang/crates.io-index" 502 | checksum = "8c2bdb6314ec10835cd3293dd268473a835c02b7b352e788be788b3c6ca6bb16" 503 | dependencies = [ 504 | "libc", 505 | "log", 506 | "miow", 507 | "ntapi", 508 | "winapi", 509 | ] 510 | 511 | [[package]] 512 | name = "miow" 513 | version = "0.3.7" 514 | source = "registry+https://github.com/rust-lang/crates.io-index" 515 | checksum = "b9f1c5b025cda876f66ef43a113f91ebc9f4ccef34843000e0adf6ebbab84e21" 516 | dependencies = [ 517 | "winapi", 518 | ] 519 | 520 | [[package]] 521 | name = "multipart" 522 | version = "0.17.1" 523 | source = "registry+https://github.com/rust-lang/crates.io-index" 524 | checksum = "d050aeedc89243f5347c3e237e3e13dc76fbe4ae3742a57b94dc14f69acf76d4" 525 | dependencies = [ 526 | "buf_redux", 527 | "httparse", 528 | "log", 529 | "mime", 530 | "mime_guess", 531 | "quick-error", 532 | "rand 0.7.3", 533 | "safemem", 534 | "tempfile", 535 | "twoway", 536 | ] 537 | 538 | [[package]] 539 | name = "native-tls" 540 | version = "0.2.8" 541 | source = "registry+https://github.com/rust-lang/crates.io-index" 542 | checksum = "48ba9f7719b5a0f42f338907614285fb5fd70e53858141f69898a1fb7203b24d" 543 | dependencies = [ 544 | "lazy_static", 545 | "libc", 546 | "log", 547 | "openssl", 548 | "openssl-probe", 549 | "openssl-sys", 550 | "schannel", 551 | "security-framework", 552 | "security-framework-sys", 553 | "tempfile", 554 | ] 555 | 556 | [[package]] 557 | name = "ntapi" 558 | version = "0.3.6" 559 | source = "registry+https://github.com/rust-lang/crates.io-index" 560 | checksum = "3f6bb902e437b6d86e03cce10a7e2af662292c5dfef23b65899ea3ac9354ad44" 561 | dependencies = [ 562 | "winapi", 563 | ] 564 | 565 | [[package]] 566 | name = "num_cpus" 567 | version = "1.13.0" 568 | source = "registry+https://github.com/rust-lang/crates.io-index" 569 | checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3" 570 | dependencies = [ 571 | "hermit-abi", 572 | "libc", 573 | ] 574 | 575 | [[package]] 576 | name = "once_cell" 577 | version = "1.8.0" 578 | source = "registry+https://github.com/rust-lang/crates.io-index" 579 | checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" 580 | 581 | [[package]] 582 | name = "opaque-debug" 583 | version = "0.3.0" 584 | source = "registry+https://github.com/rust-lang/crates.io-index" 585 | checksum = "624a8340c38c1b80fd549087862da4ba43e08858af025b236e509b6649fc13d5" 586 | 587 | [[package]] 588 | name = "openssl" 589 | version = "0.10.36" 590 | source = "registry+https://github.com/rust-lang/crates.io-index" 591 | checksum = "8d9facdb76fec0b73c406f125d44d86fdad818d66fef0531eec9233ca425ff4a" 592 | dependencies = [ 593 | "bitflags", 594 | "cfg-if", 595 | "foreign-types", 596 | "libc", 597 | "once_cell", 598 | "openssl-sys", 599 | ] 600 | 601 | [[package]] 602 | name = "openssl-probe" 603 | version = "0.1.4" 604 | source = "registry+https://github.com/rust-lang/crates.io-index" 605 | checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" 606 | 607 | [[package]] 608 | name = "openssl-sys" 609 | version = "0.9.67" 610 | source = "registry+https://github.com/rust-lang/crates.io-index" 611 | checksum = "69df2d8dfc6ce3aaf44b40dec6f487d5a886516cf6879c49e98e0710f310a058" 612 | dependencies = [ 613 | "autocfg", 614 | "cc", 615 | "libc", 616 | "pkg-config", 617 | "vcpkg", 618 | ] 619 | 620 | [[package]] 621 | name = "percent-encoding" 622 | version = "2.1.0" 623 | source = "registry+https://github.com/rust-lang/crates.io-index" 624 | checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" 625 | 626 | [[package]] 627 | name = "pin-project" 628 | version = "1.0.8" 629 | source = "registry+https://github.com/rust-lang/crates.io-index" 630 | checksum = "576bc800220cc65dac09e99e97b08b358cfab6e17078de8dc5fee223bd2d0c08" 631 | dependencies = [ 632 | "pin-project-internal", 633 | ] 634 | 635 | [[package]] 636 | name = "pin-project-internal" 637 | version = "1.0.8" 638 | source = "registry+https://github.com/rust-lang/crates.io-index" 639 | checksum = "6e8fe8163d14ce7f0cdac2e040116f22eac817edabff0be91e8aff7e9accf389" 640 | dependencies = [ 641 | "proc-macro2", 642 | "quote", 643 | "syn", 644 | ] 645 | 646 | [[package]] 647 | name = "pin-project-lite" 648 | version = "0.2.7" 649 | source = "registry+https://github.com/rust-lang/crates.io-index" 650 | checksum = "8d31d11c69a6b52a174b42bdc0c30e5e11670f90788b2c471c31c1d17d449443" 651 | 652 | [[package]] 653 | name = "pin-utils" 654 | version = "0.1.0" 655 | source = "registry+https://github.com/rust-lang/crates.io-index" 656 | checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 657 | 658 | [[package]] 659 | name = "pkg-config" 660 | version = "0.3.20" 661 | source = "registry+https://github.com/rust-lang/crates.io-index" 662 | checksum = "7c9b1041b4387893b91ee6746cddfc28516aff326a3519fb2adf820932c5e6cb" 663 | 664 | [[package]] 665 | name = "ppv-lite86" 666 | version = "0.2.10" 667 | source = "registry+https://github.com/rust-lang/crates.io-index" 668 | checksum = "ac74c624d6b2d21f425f752262f42188365d7b8ff1aff74c82e45136510a4857" 669 | 670 | [[package]] 671 | name = "proc-macro2" 672 | version = "1.0.29" 673 | source = "registry+https://github.com/rust-lang/crates.io-index" 674 | checksum = "b9f5105d4fdaab20335ca9565e106a5d9b82b6219b5ba735731124ac6711d23d" 675 | dependencies = [ 676 | "unicode-xid", 677 | ] 678 | 679 | [[package]] 680 | name = "quick-error" 681 | version = "1.2.3" 682 | source = "registry+https://github.com/rust-lang/crates.io-index" 683 | checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" 684 | 685 | [[package]] 686 | name = "quote" 687 | version = "1.0.9" 688 | source = "registry+https://github.com/rust-lang/crates.io-index" 689 | checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" 690 | dependencies = [ 691 | "proc-macro2", 692 | ] 693 | 694 | [[package]] 695 | name = "rand" 696 | version = "0.7.3" 697 | source = "registry+https://github.com/rust-lang/crates.io-index" 698 | checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" 699 | dependencies = [ 700 | "getrandom 0.1.16", 701 | "libc", 702 | "rand_chacha 0.2.2", 703 | "rand_core 0.5.1", 704 | "rand_hc 0.2.0", 705 | ] 706 | 707 | [[package]] 708 | name = "rand" 709 | version = "0.8.4" 710 | source = "registry+https://github.com/rust-lang/crates.io-index" 711 | checksum = "2e7573632e6454cf6b99d7aac4ccca54be06da05aca2ef7423d22d27d4d4bcd8" 712 | dependencies = [ 713 | "libc", 714 | "rand_chacha 0.3.1", 715 | "rand_core 0.6.3", 716 | "rand_hc 0.3.1", 717 | ] 718 | 719 | [[package]] 720 | name = "rand_chacha" 721 | version = "0.2.2" 722 | source = "registry+https://github.com/rust-lang/crates.io-index" 723 | checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" 724 | dependencies = [ 725 | "ppv-lite86", 726 | "rand_core 0.5.1", 727 | ] 728 | 729 | [[package]] 730 | name = "rand_chacha" 731 | version = "0.3.1" 732 | source = "registry+https://github.com/rust-lang/crates.io-index" 733 | checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 734 | dependencies = [ 735 | "ppv-lite86", 736 | "rand_core 0.6.3", 737 | ] 738 | 739 | [[package]] 740 | name = "rand_core" 741 | version = "0.5.1" 742 | source = "registry+https://github.com/rust-lang/crates.io-index" 743 | checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" 744 | dependencies = [ 745 | "getrandom 0.1.16", 746 | ] 747 | 748 | [[package]] 749 | name = "rand_core" 750 | version = "0.6.3" 751 | source = "registry+https://github.com/rust-lang/crates.io-index" 752 | checksum = "d34f1408f55294453790c48b2f1ebbb1c5b4b7563eb1f418bcfcfdbb06ebb4e7" 753 | dependencies = [ 754 | "getrandom 0.2.3", 755 | ] 756 | 757 | [[package]] 758 | name = "rand_hc" 759 | version = "0.2.0" 760 | source = "registry+https://github.com/rust-lang/crates.io-index" 761 | checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" 762 | dependencies = [ 763 | "rand_core 0.5.1", 764 | ] 765 | 766 | [[package]] 767 | name = "rand_hc" 768 | version = "0.3.1" 769 | source = "registry+https://github.com/rust-lang/crates.io-index" 770 | checksum = "d51e9f596de227fda2ea6c84607f5558e196eeaf43c986b724ba4fb8fdf497e7" 771 | dependencies = [ 772 | "rand_core 0.6.3", 773 | ] 774 | 775 | [[package]] 776 | name = "redox_syscall" 777 | version = "0.2.10" 778 | source = "registry+https://github.com/rust-lang/crates.io-index" 779 | checksum = "8383f39639269cde97d255a32bdb68c047337295414940c68bdd30c2e13203ff" 780 | dependencies = [ 781 | "bitflags", 782 | ] 783 | 784 | [[package]] 785 | name = "remove_dir_all" 786 | version = "0.5.3" 787 | source = "registry+https://github.com/rust-lang/crates.io-index" 788 | checksum = "3acd125665422973a33ac9d3dd2df85edad0f4ae9b00dafb1a05e43a9f5ef8e7" 789 | dependencies = [ 790 | "winapi", 791 | ] 792 | 793 | [[package]] 794 | name = "reqwest" 795 | version = "0.11.4" 796 | source = "registry+https://github.com/rust-lang/crates.io-index" 797 | checksum = "246e9f61b9bb77df069a947682be06e31ac43ea37862e244a69f177694ea6d22" 798 | dependencies = [ 799 | "base64", 800 | "bytes", 801 | "encoding_rs", 802 | "futures-core", 803 | "futures-util", 804 | "http", 805 | "http-body", 806 | "hyper", 807 | "hyper-tls", 808 | "ipnet", 809 | "js-sys", 810 | "lazy_static", 811 | "log", 812 | "mime", 813 | "mime_guess", 814 | "native-tls", 815 | "percent-encoding", 816 | "pin-project-lite", 817 | "serde", 818 | "serde_json", 819 | "serde_urlencoded", 820 | "tokio", 821 | "tokio-native-tls", 822 | "url", 823 | "wasm-bindgen", 824 | "wasm-bindgen-futures", 825 | "web-sys", 826 | "winreg", 827 | ] 828 | 829 | [[package]] 830 | name = "ryu" 831 | version = "1.0.5" 832 | source = "registry+https://github.com/rust-lang/crates.io-index" 833 | checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e" 834 | 835 | [[package]] 836 | name = "safemem" 837 | version = "0.3.3" 838 | source = "registry+https://github.com/rust-lang/crates.io-index" 839 | checksum = "ef703b7cb59335eae2eb93ceb664c0eb7ea6bf567079d843e09420219668e072" 840 | 841 | [[package]] 842 | name = "schannel" 843 | version = "0.1.19" 844 | source = "registry+https://github.com/rust-lang/crates.io-index" 845 | checksum = "8f05ba609c234e60bee0d547fe94a4c7e9da733d1c962cf6e59efa4cd9c8bc75" 846 | dependencies = [ 847 | "lazy_static", 848 | "winapi", 849 | ] 850 | 851 | [[package]] 852 | name = "scoped-tls" 853 | version = "1.0.0" 854 | source = "registry+https://github.com/rust-lang/crates.io-index" 855 | checksum = "ea6a9290e3c9cf0f18145ef7ffa62d68ee0bf5fcd651017e586dc7fd5da448c2" 856 | 857 | [[package]] 858 | name = "security-framework" 859 | version = "2.4.2" 860 | source = "registry+https://github.com/rust-lang/crates.io-index" 861 | checksum = "525bc1abfda2e1998d152c45cf13e696f76d0a4972310b22fac1658b05df7c87" 862 | dependencies = [ 863 | "bitflags", 864 | "core-foundation", 865 | "core-foundation-sys", 866 | "libc", 867 | "security-framework-sys", 868 | ] 869 | 870 | [[package]] 871 | name = "security-framework-sys" 872 | version = "2.4.2" 873 | source = "registry+https://github.com/rust-lang/crates.io-index" 874 | checksum = "a9dd14d83160b528b7bfd66439110573efcfbe281b17fc2ca9f39f550d619c7e" 875 | dependencies = [ 876 | "core-foundation-sys", 877 | "libc", 878 | ] 879 | 880 | [[package]] 881 | name = "serde" 882 | version = "1.0.130" 883 | source = "registry+https://github.com/rust-lang/crates.io-index" 884 | checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" 885 | dependencies = [ 886 | "serde_derive", 887 | ] 888 | 889 | [[package]] 890 | name = "serde_derive" 891 | version = "1.0.130" 892 | source = "registry+https://github.com/rust-lang/crates.io-index" 893 | checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" 894 | dependencies = [ 895 | "proc-macro2", 896 | "quote", 897 | "syn", 898 | ] 899 | 900 | [[package]] 901 | name = "serde_json" 902 | version = "1.0.68" 903 | source = "registry+https://github.com/rust-lang/crates.io-index" 904 | checksum = "0f690853975602e1bfe1ccbf50504d67174e3bcf340f23b5ea9992e0587a52d8" 905 | dependencies = [ 906 | "itoa", 907 | "ryu", 908 | "serde", 909 | ] 910 | 911 | [[package]] 912 | name = "serde_urlencoded" 913 | version = "0.7.0" 914 | source = "registry+https://github.com/rust-lang/crates.io-index" 915 | checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" 916 | dependencies = [ 917 | "form_urlencoded", 918 | "itoa", 919 | "ryu", 920 | "serde", 921 | ] 922 | 923 | [[package]] 924 | name = "sha-1" 925 | version = "0.9.8" 926 | source = "registry+https://github.com/rust-lang/crates.io-index" 927 | checksum = "99cd6713db3cf16b6c84e06321e049a9b9f699826e16096d23bbcc44d15d51a6" 928 | dependencies = [ 929 | "block-buffer", 930 | "cfg-if", 931 | "cpufeatures", 932 | "digest", 933 | "opaque-debug", 934 | ] 935 | 936 | [[package]] 937 | name = "slab" 938 | version = "0.4.4" 939 | source = "registry+https://github.com/rust-lang/crates.io-index" 940 | checksum = "c307a32c1c5c437f38c7fd45d753050587732ba8628319fbdf12a7e289ccc590" 941 | 942 | [[package]] 943 | name = "socket2" 944 | version = "0.4.2" 945 | source = "registry+https://github.com/rust-lang/crates.io-index" 946 | checksum = "5dc90fe6c7be1a323296982db1836d1ea9e47b6839496dde9a541bc496df3516" 947 | dependencies = [ 948 | "libc", 949 | "winapi", 950 | ] 951 | 952 | [[package]] 953 | name = "syn" 954 | version = "1.0.77" 955 | source = "registry+https://github.com/rust-lang/crates.io-index" 956 | checksum = "5239bc68e0fef57495900cfea4e8dc75596d9a319d7e16b1e0a440d24e6fe0a0" 957 | dependencies = [ 958 | "proc-macro2", 959 | "quote", 960 | "unicode-xid", 961 | ] 962 | 963 | [[package]] 964 | name = "tempfile" 965 | version = "3.2.0" 966 | source = "registry+https://github.com/rust-lang/crates.io-index" 967 | checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22" 968 | dependencies = [ 969 | "cfg-if", 970 | "libc", 971 | "rand 0.8.4", 972 | "redox_syscall", 973 | "remove_dir_all", 974 | "winapi", 975 | ] 976 | 977 | [[package]] 978 | name = "time" 979 | version = "0.1.43" 980 | source = "registry+https://github.com/rust-lang/crates.io-index" 981 | checksum = "ca8a50ef2360fbd1eeb0ecd46795a87a19024eb4b53c5dc916ca1fd95fe62438" 982 | dependencies = [ 983 | "libc", 984 | "winapi", 985 | ] 986 | 987 | [[package]] 988 | name = "tinyvec" 989 | version = "1.5.0" 990 | source = "registry+https://github.com/rust-lang/crates.io-index" 991 | checksum = "f83b2a3d4d9091d0abd7eba4dc2710b1718583bd4d8992e2190720ea38f391f7" 992 | dependencies = [ 993 | "tinyvec_macros", 994 | ] 995 | 996 | [[package]] 997 | name = "tinyvec_macros" 998 | version = "0.1.0" 999 | source = "registry+https://github.com/rust-lang/crates.io-index" 1000 | checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" 1001 | 1002 | [[package]] 1003 | name = "tokio" 1004 | version = "1.12.0" 1005 | source = "registry+https://github.com/rust-lang/crates.io-index" 1006 | checksum = "c2c2416fdedca8443ae44b4527de1ea633af61d8f7169ffa6e72c5b53d24efcc" 1007 | dependencies = [ 1008 | "autocfg", 1009 | "bytes", 1010 | "libc", 1011 | "memchr", 1012 | "mio", 1013 | "num_cpus", 1014 | "pin-project-lite", 1015 | "tokio-macros", 1016 | "winapi", 1017 | ] 1018 | 1019 | [[package]] 1020 | name = "tokio-macros" 1021 | version = "1.4.0" 1022 | source = "registry+https://github.com/rust-lang/crates.io-index" 1023 | checksum = "6bad447894d469f905c43bffb355333bcc9eaaaf736d2815214e962714cad02d" 1024 | dependencies = [ 1025 | "proc-macro2", 1026 | "quote", 1027 | "syn", 1028 | ] 1029 | 1030 | [[package]] 1031 | name = "tokio-native-tls" 1032 | version = "0.3.0" 1033 | source = "registry+https://github.com/rust-lang/crates.io-index" 1034 | checksum = "f7d995660bd2b7f8c1568414c1126076c13fbb725c40112dc0120b78eb9b717b" 1035 | dependencies = [ 1036 | "native-tls", 1037 | "tokio", 1038 | ] 1039 | 1040 | [[package]] 1041 | name = "tokio-stream" 1042 | version = "0.1.7" 1043 | source = "registry+https://github.com/rust-lang/crates.io-index" 1044 | checksum = "7b2f3f698253f03119ac0102beaa64f67a67e08074d03a22d18784104543727f" 1045 | dependencies = [ 1046 | "futures-core", 1047 | "pin-project-lite", 1048 | "tokio", 1049 | ] 1050 | 1051 | [[package]] 1052 | name = "tokio-tungstenite" 1053 | version = "0.13.0" 1054 | source = "registry+https://github.com/rust-lang/crates.io-index" 1055 | checksum = "e1a5f475f1b9d077ea1017ecbc60890fda8e54942d680ca0b1d2b47cfa2d861b" 1056 | dependencies = [ 1057 | "futures-util", 1058 | "log", 1059 | "pin-project", 1060 | "tokio", 1061 | "tungstenite", 1062 | ] 1063 | 1064 | [[package]] 1065 | name = "tokio-util" 1066 | version = "0.6.8" 1067 | source = "registry+https://github.com/rust-lang/crates.io-index" 1068 | checksum = "08d3725d3efa29485e87311c5b699de63cde14b00ed4d256b8318aa30ca452cd" 1069 | dependencies = [ 1070 | "bytes", 1071 | "futures-core", 1072 | "futures-sink", 1073 | "log", 1074 | "pin-project-lite", 1075 | "tokio", 1076 | ] 1077 | 1078 | [[package]] 1079 | name = "tower-service" 1080 | version = "0.3.1" 1081 | source = "registry+https://github.com/rust-lang/crates.io-index" 1082 | checksum = "360dfd1d6d30e05fda32ace2c8c70e9c0a9da713275777f5a4dbb8a1893930c6" 1083 | 1084 | [[package]] 1085 | name = "tracing" 1086 | version = "0.1.28" 1087 | source = "registry+https://github.com/rust-lang/crates.io-index" 1088 | checksum = "84f96e095c0c82419687c20ddf5cb3eadb61f4e1405923c9dc8e53a1adacbda8" 1089 | dependencies = [ 1090 | "cfg-if", 1091 | "log", 1092 | "pin-project-lite", 1093 | "tracing-core", 1094 | ] 1095 | 1096 | [[package]] 1097 | name = "tracing-core" 1098 | version = "0.1.20" 1099 | source = "registry+https://github.com/rust-lang/crates.io-index" 1100 | checksum = "46125608c26121c81b0c6d693eab5a420e416da7e43c426d2e8f7df8da8a3acf" 1101 | dependencies = [ 1102 | "lazy_static", 1103 | ] 1104 | 1105 | [[package]] 1106 | name = "try-lock" 1107 | version = "0.2.3" 1108 | source = "registry+https://github.com/rust-lang/crates.io-index" 1109 | checksum = "59547bce71d9c38b83d9c0e92b6066c4253371f15005def0c30d9657f50c7642" 1110 | 1111 | [[package]] 1112 | name = "tungstenite" 1113 | version = "0.12.0" 1114 | source = "registry+https://github.com/rust-lang/crates.io-index" 1115 | checksum = "8ada8297e8d70872fa9a551d93250a9f407beb9f37ef86494eb20012a2ff7c24" 1116 | dependencies = [ 1117 | "base64", 1118 | "byteorder", 1119 | "bytes", 1120 | "http", 1121 | "httparse", 1122 | "input_buffer", 1123 | "log", 1124 | "rand 0.8.4", 1125 | "sha-1", 1126 | "url", 1127 | "utf-8", 1128 | ] 1129 | 1130 | [[package]] 1131 | name = "twoway" 1132 | version = "0.1.8" 1133 | source = "registry+https://github.com/rust-lang/crates.io-index" 1134 | checksum = "59b11b2b5241ba34be09c3cc85a36e56e48f9888862e19cedf23336d35316ed1" 1135 | dependencies = [ 1136 | "memchr", 1137 | ] 1138 | 1139 | [[package]] 1140 | name = "typenum" 1141 | version = "1.14.0" 1142 | source = "registry+https://github.com/rust-lang/crates.io-index" 1143 | checksum = "b63708a265f51345575b27fe43f9500ad611579e764c79edbc2037b1121959ec" 1144 | 1145 | [[package]] 1146 | name = "unicase" 1147 | version = "2.6.0" 1148 | source = "registry+https://github.com/rust-lang/crates.io-index" 1149 | checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" 1150 | dependencies = [ 1151 | "version_check", 1152 | ] 1153 | 1154 | [[package]] 1155 | name = "unicode-bidi" 1156 | version = "0.3.6" 1157 | source = "registry+https://github.com/rust-lang/crates.io-index" 1158 | checksum = "246f4c42e67e7a4e3c6106ff716a5d067d4132a642840b242e357e468a2a0085" 1159 | 1160 | [[package]] 1161 | name = "unicode-normalization" 1162 | version = "0.1.19" 1163 | source = "registry+https://github.com/rust-lang/crates.io-index" 1164 | checksum = "d54590932941a9e9266f0832deed84ebe1bf2e4c9e4a3554d393d18f5e854bf9" 1165 | dependencies = [ 1166 | "tinyvec", 1167 | ] 1168 | 1169 | [[package]] 1170 | name = "unicode-xid" 1171 | version = "0.2.2" 1172 | source = "registry+https://github.com/rust-lang/crates.io-index" 1173 | checksum = "8ccb82d61f80a663efe1f787a51b16b5a51e3314d6ac365b08639f52387b33f3" 1174 | 1175 | [[package]] 1176 | name = "url" 1177 | version = "2.2.2" 1178 | source = "registry+https://github.com/rust-lang/crates.io-index" 1179 | checksum = "a507c383b2d33b5fc35d1861e77e6b383d158b2da5e14fe51b83dfedf6fd578c" 1180 | dependencies = [ 1181 | "form_urlencoded", 1182 | "idna", 1183 | "matches", 1184 | "percent-encoding", 1185 | ] 1186 | 1187 | [[package]] 1188 | name = "utf-8" 1189 | version = "0.7.6" 1190 | source = "registry+https://github.com/rust-lang/crates.io-index" 1191 | checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" 1192 | 1193 | [[package]] 1194 | name = "vcpkg" 1195 | version = "0.2.15" 1196 | source = "registry+https://github.com/rust-lang/crates.io-index" 1197 | checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" 1198 | 1199 | [[package]] 1200 | name = "version_check" 1201 | version = "0.9.3" 1202 | source = "registry+https://github.com/rust-lang/crates.io-index" 1203 | checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe" 1204 | 1205 | [[package]] 1206 | name = "want" 1207 | version = "0.3.0" 1208 | source = "registry+https://github.com/rust-lang/crates.io-index" 1209 | checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" 1210 | dependencies = [ 1211 | "log", 1212 | "try-lock", 1213 | ] 1214 | 1215 | [[package]] 1216 | name = "warp" 1217 | version = "0.3.1" 1218 | source = "registry+https://github.com/rust-lang/crates.io-index" 1219 | checksum = "332d47745e9a0c38636dbd454729b147d16bd1ed08ae67b3ab281c4506771054" 1220 | dependencies = [ 1221 | "bytes", 1222 | "futures", 1223 | "headers", 1224 | "http", 1225 | "hyper", 1226 | "log", 1227 | "mime", 1228 | "mime_guess", 1229 | "multipart", 1230 | "percent-encoding", 1231 | "pin-project", 1232 | "scoped-tls", 1233 | "serde", 1234 | "serde_json", 1235 | "serde_urlencoded", 1236 | "tokio", 1237 | "tokio-stream", 1238 | "tokio-tungstenite", 1239 | "tokio-util", 1240 | "tower-service", 1241 | "tracing", 1242 | ] 1243 | 1244 | [[package]] 1245 | name = "wasi" 1246 | version = "0.9.0+wasi-snapshot-preview1" 1247 | source = "registry+https://github.com/rust-lang/crates.io-index" 1248 | checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" 1249 | 1250 | [[package]] 1251 | name = "wasi" 1252 | version = "0.10.2+wasi-snapshot-preview1" 1253 | source = "registry+https://github.com/rust-lang/crates.io-index" 1254 | checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" 1255 | 1256 | [[package]] 1257 | name = "wasm-bindgen" 1258 | version = "0.2.78" 1259 | source = "registry+https://github.com/rust-lang/crates.io-index" 1260 | checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" 1261 | dependencies = [ 1262 | "cfg-if", 1263 | "serde", 1264 | "serde_json", 1265 | "wasm-bindgen-macro", 1266 | ] 1267 | 1268 | [[package]] 1269 | name = "wasm-bindgen-backend" 1270 | version = "0.2.78" 1271 | source = "registry+https://github.com/rust-lang/crates.io-index" 1272 | checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" 1273 | dependencies = [ 1274 | "bumpalo", 1275 | "lazy_static", 1276 | "log", 1277 | "proc-macro2", 1278 | "quote", 1279 | "syn", 1280 | "wasm-bindgen-shared", 1281 | ] 1282 | 1283 | [[package]] 1284 | name = "wasm-bindgen-futures" 1285 | version = "0.4.28" 1286 | source = "registry+https://github.com/rust-lang/crates.io-index" 1287 | checksum = "8e8d7523cb1f2a4c96c1317ca690031b714a51cc14e05f712446691f413f5d39" 1288 | dependencies = [ 1289 | "cfg-if", 1290 | "js-sys", 1291 | "wasm-bindgen", 1292 | "web-sys", 1293 | ] 1294 | 1295 | [[package]] 1296 | name = "wasm-bindgen-macro" 1297 | version = "0.2.78" 1298 | source = "registry+https://github.com/rust-lang/crates.io-index" 1299 | checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" 1300 | dependencies = [ 1301 | "quote", 1302 | "wasm-bindgen-macro-support", 1303 | ] 1304 | 1305 | [[package]] 1306 | name = "wasm-bindgen-macro-support" 1307 | version = "0.2.78" 1308 | source = "registry+https://github.com/rust-lang/crates.io-index" 1309 | checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" 1310 | dependencies = [ 1311 | "proc-macro2", 1312 | "quote", 1313 | "syn", 1314 | "wasm-bindgen-backend", 1315 | "wasm-bindgen-shared", 1316 | ] 1317 | 1318 | [[package]] 1319 | name = "wasm-bindgen-shared" 1320 | version = "0.2.78" 1321 | source = "registry+https://github.com/rust-lang/crates.io-index" 1322 | checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" 1323 | 1324 | [[package]] 1325 | name = "web-sys" 1326 | version = "0.3.55" 1327 | source = "registry+https://github.com/rust-lang/crates.io-index" 1328 | checksum = "38eb105f1c59d9eaa6b5cdc92b859d85b926e82cb2e0945cd0c9259faa6fe9fb" 1329 | dependencies = [ 1330 | "js-sys", 1331 | "wasm-bindgen", 1332 | ] 1333 | 1334 | [[package]] 1335 | name = "webbrowser" 1336 | version = "0.5.5" 1337 | source = "registry+https://github.com/rust-lang/crates.io-index" 1338 | checksum = "ecad156490d6b620308ed411cfee90d280b3cbd13e189ea0d3fada8acc89158a" 1339 | dependencies = [ 1340 | "web-sys", 1341 | "widestring", 1342 | "winapi", 1343 | ] 1344 | 1345 | [[package]] 1346 | name = "widestring" 1347 | version = "0.4.3" 1348 | source = "registry+https://github.com/rust-lang/crates.io-index" 1349 | checksum = "c168940144dd21fd8046987c16a46a33d5fc84eec29ef9dcddc2ac9e31526b7c" 1350 | 1351 | [[package]] 1352 | name = "winapi" 1353 | version = "0.3.9" 1354 | source = "registry+https://github.com/rust-lang/crates.io-index" 1355 | checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" 1356 | dependencies = [ 1357 | "winapi-i686-pc-windows-gnu", 1358 | "winapi-x86_64-pc-windows-gnu", 1359 | ] 1360 | 1361 | [[package]] 1362 | name = "winapi-i686-pc-windows-gnu" 1363 | version = "0.4.0" 1364 | source = "registry+https://github.com/rust-lang/crates.io-index" 1365 | checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" 1366 | 1367 | [[package]] 1368 | name = "winapi-x86_64-pc-windows-gnu" 1369 | version = "0.4.0" 1370 | source = "registry+https://github.com/rust-lang/crates.io-index" 1371 | checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" 1372 | 1373 | [[package]] 1374 | name = "winreg" 1375 | version = "0.7.0" 1376 | source = "registry+https://github.com/rust-lang/crates.io-index" 1377 | checksum = "0120db82e8a1e0b9fb3345a539c478767c0048d842860994d96113d5b667bd69" 1378 | dependencies = [ 1379 | "winapi", 1380 | ] 1381 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "mcsoft-auth" 3 | version = "0.1.0" 4 | edition = "2018" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | anyhow = "1.0.44" 10 | dotenv = "0.15.0" 11 | rand = "0.8.4" 12 | reqwest = { version = "0.11.4", features = ["json", "multipart"] } 13 | serde = { version = "1.0.130", features = ["derive"] } 14 | serde_json = "1.0.68" 15 | tokio = { version = "1.12.0", features = ["macros", "rt-multi-thread"] } 16 | warp = "0.3.1" 17 | webbrowser = "0.5.5" 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 ALinuxPerson 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Authenticating to Minecraft with the Microsoft Authentication Scheme from Rust 2 | This program showcases an implementation of the microsoft authentication scheme for Minecraft, 3 | written in Rust. 4 | 5 | # Requirements 6 | You need to obtain a client id and client secret by creating an [Azure application]. Steps on obtaining the client id and 7 | client secret will be seen in the next section. 8 | 9 | You will also need to provide a redirect uri. This program assumes that you've set the redirect uri in Azure to be 10 | `localhost`. 11 | 12 | A port is also needed. If the port isn't given or is invalid, it will try to parse it from the redirect uri. If it 13 | doesn't exist in the redirect uri, it is set to 80. 14 | 15 | In order to input these requirements, you have two methods: 16 | * Input the variable using environment variables while calling `cargo run`, or 17 | * Use a `.env` file, placing it within this directory. 18 | 19 | Here are the variables needed. 20 | 21 | * `CLIENT_ID`: The client id you got in your azure application. 22 | * `CLIENT_SECRET`: The client secret you got in your azure application. 23 | * `REDIRECT_URI`: The redirect uri you gave in your azure application. 24 | * `PORT` (Optional): The port you gave in your redirect uri. If not given, it is inferred. 25 | 26 | # Steps on obtaining a client id and a client secret from Azure 27 | 1. Visit portal.azure.com and input your credentials. 28 | 2. From the search bar in the top middle of the screen, search for 'Azure Active Directory'. 29 | 3. From the sidebar, click on 'App registrations' from the 'Manage' section. 30 | 4. Click on 'New Registration' in the menu bar. 31 | 5. Set the name of your application to anything you want. 32 | 6. Set the supported account type to 'Personal Microsoft accounts only'. 33 | 7. Set the type of the Redirect URI to 'Web', and input your redirect uri there. 34 | 8. Copy the client id to a safe place. 35 | 9. Click on 'Add a certificate or secret' under 'Client credentials'. 36 | 10. Click on 'New client secret' under 'Client secrets'. 37 | 11. Click on add, optionally adding a description. 38 | 12. Copy the client secret to a safe place __immediately__, as the first three digits will only be shown to you afterwards. 39 | 13. You should now have the client id and client secret. 40 | 41 | # Running it 42 | 43 | 1. Install Rust from their website: www.rust-lang.org 44 | 2. Clone this repository: 45 | 46 | ```shell 47 | $ git clone https://github.com/ALinuxPerson/mcsoft-auth.git 48 | ``` 49 | 50 | 3. Provide the environment variables above in the Requirements section. 51 | 4. Run it via `cargo run`. 52 | 53 | If all goes well, the first that should pop up in your terminal is this: 54 | 55 | ``` 56 | Now awaiting code. 57 | ``` 58 | 59 | You should have gotten your default browser to open a link to the microsoft oauth page. If nothing popped and an error 60 | occurred in your terminal, you should be able to get the link from there. 61 | 62 | Follow the instructions on the link, and then you should get a message on your browser as text like this: 63 | 64 | ``` 65 | Successfully received query 66 | ``` 67 | 68 | Going back to your terminal, you should get the following messages in this order: 69 | 70 | ``` 71 | Now getting the access token. 72 | Now authenticating with Xbox Live. 73 | Now getting an Xbox Live Security Token (XSTS). 74 | Now authenticating with Minecraft. 75 | Checking for game ownership. 76 | ``` 77 | 78 | Up to this point, this should be the messages that you'll if you have _at least_ a microsoft account. However, it 79 | doesn't assume that you have a valid copy of Minecraft. 80 | 81 | These are the following possibilities that could happen: 82 | * If you own minecraft, it succeeds and continues. 83 | * If you __don't__ have minecraft, one of these messages will show: 84 | 85 | ``` 86 | Error: product_minecraft item doesn't exist. do you really own the game? 87 | ``` 88 | 89 | or 90 | 91 | ``` 92 | Error: game_minecraft item doesn't exist. do you really own the game? 93 | ``` 94 | 95 | Typically, it should be the first error. 96 | 97 | Now, if the game ownership check succeeds, the next lines from your terminal should be as follows: 98 | 99 | ``` 100 | Getting game profile. 101 | Congratulations, you authenticated to minecraft from Rust! 102 | access_token=REDACTED username=REDACTED uuid=REDACTED 103 | ``` 104 | 105 | Of course, replacing `REDACTED` with the real, respective values. 106 | 107 | # What this can't do 108 | 109 | This program can't: 110 | * Support skins. 111 | * Handle errors. If an error occurs while during one of the steps, you'll instead get an esoteric error message, 112 | probably from serde complaining that it can't be parsed correctly. 113 | 114 | # Technical Information 115 | 116 | The technical information on how this program works internally can be seen in the (unofficial) 117 | [Microsoft Authentication Scheme] documentation, and also by looking at the source code of this program. 118 | 119 | [Azure application]: https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app 120 | [Microsoft Authentication Scheme]: https://wiki.vg/Microsoft_Authentication_Scheme -------------------------------------------------------------------------------- /src/main.rs: -------------------------------------------------------------------------------- 1 | use std::env; 2 | use anyhow::Context; 3 | use warp::Filter; 4 | use std::sync::mpsc; 5 | use serde::Deserialize; 6 | use std::borrow::Cow; 7 | use rand::Rng; 8 | use rand::distributions::Alphanumeric; 9 | use reqwest::Url; 10 | 11 | #[derive(Deserialize)] 12 | pub struct Query { 13 | pub code: String, 14 | pub state: String, 15 | } 16 | 17 | #[derive(Deserialize)] 18 | pub struct AccessToken { 19 | pub access_token: String, 20 | } 21 | 22 | #[derive(Deserialize)] 23 | pub struct Xui { 24 | #[serde(rename = "uhs")] 25 | pub user_hash: String, 26 | } 27 | 28 | #[derive(Deserialize)] 29 | pub struct DisplayClaims { 30 | pub xui: Vec, 31 | } 32 | 33 | #[derive(Deserialize)] 34 | pub struct AuthenticateWithXboxLiveOrXsts { 35 | #[serde(rename = "Token")] 36 | pub token: String, 37 | 38 | #[serde(rename = "DisplayClaims")] 39 | pub display_claims: DisplayClaims, 40 | } 41 | 42 | #[derive(Deserialize, PartialEq)] 43 | pub struct Item { 44 | pub name: Cow<'static, str>, 45 | // pub signature: String, // todo: signature verification 46 | } 47 | 48 | impl Item { 49 | pub const PRODUCT_MINECRAFT: Self = Self { 50 | name: Cow::Borrowed("product_minecraft") 51 | }; 52 | pub const GAME_MINECRAFT: Self = Self { 53 | name: Cow::Borrowed("game_minecraft") 54 | }; 55 | } 56 | 57 | #[derive(Deserialize)] 58 | pub struct Store { 59 | pub items: Vec, 60 | 61 | // pub signature: String, // todo: signature verification 62 | 63 | #[serde(rename = "keyId")] 64 | pub key_id: String, 65 | } 66 | 67 | impl AuthenticateWithXboxLiveOrXsts { 68 | pub fn extract_essential_information(self) -> anyhow::Result<(String, String)> { 69 | let token = self.token; 70 | let user_hash = self.display_claims.xui 71 | .into_iter() 72 | .next() 73 | .context("no xui found")? 74 | .user_hash; 75 | 76 | Ok((token, user_hash)) 77 | } 78 | } 79 | 80 | #[derive(Deserialize)] 81 | pub struct Profile { 82 | pub id: String, 83 | pub name: String, 84 | } 85 | 86 | async fn receive_query(port: u16) -> Query { 87 | let (sender, receiver) = mpsc::sync_channel(1); 88 | let route = warp::get() 89 | .and(warp::filters::query::query()) 90 | .map(move |query: Query| { 91 | sender.send(query).expect("failed to send query"); 92 | "Successfully received query" 93 | }); 94 | 95 | tokio::task::spawn(warp::serve(route).run(([127, 0, 0, 1], port))); 96 | 97 | receiver.recv().expect("channel has hung up") 98 | } 99 | 100 | fn random_string() -> String { 101 | rand::thread_rng() 102 | .sample_iter(Alphanumeric) 103 | .take(16) 104 | .map(char::from) 105 | .collect() 106 | } 107 | 108 | #[tokio::main] 109 | async fn main() -> anyhow::Result<()> { 110 | dotenv::dotenv().ok(); 111 | 112 | let client_id = env::var("CLIENT_ID").context("CLIENT_ID is needed")?; 113 | let client_secret = env::var("CLIENT_SECRET").context("CLIENT_SECRET is needed")?; 114 | let redirect_uri: Url = env::var("REDIRECT_URI") 115 | .context("REDIRECT_URI is needed")? 116 | .parse() 117 | .context("redirect uri is not a valid url")?; 118 | 119 | match redirect_uri.domain() { 120 | Some(domain) => anyhow::ensure!(domain == "localhost" || domain == "127.0.0.1", "domain '{}' isn't valid, it must be '127.0.0.1' or 'localhost'", domain), 121 | None => anyhow::bail!("the redirect uri must have a domain") 122 | } 123 | 124 | let port = env::var("PORT") 125 | .ok() 126 | .and_then(|port| match port.parse::() { 127 | Ok(port) => Some(port), 128 | Err(_) => { 129 | eprintln!("'{}' is not a valid port, using the given redirect uri's port", port); 130 | None 131 | } 132 | }) 133 | .unwrap_or_else(|| match redirect_uri.port() { 134 | Some(port) => port, 135 | None => { 136 | eprintln!("The redirect uri '{}' doesn't have a port given, assuming port is 80", redirect_uri); 137 | 80 138 | } 139 | }); 140 | let state = random_string(); 141 | let url = format!("https://login.live.com/oauth20_authorize.srf\ 142 | ?client_id={}\ 143 | &response_type=code\ 144 | &redirect_uri={}\ 145 | &scope=XboxLive.signin%20offline_access\ 146 | &state={}", client_id, redirect_uri, state); 147 | 148 | if let Err(error) = webbrowser::open(&url) { 149 | println!("error opening browser: {}", error); 150 | println!("use this link instead:\n{}", url) 151 | } 152 | 153 | println!("Now awaiting code."); 154 | let query = receive_query(port).await; 155 | 156 | anyhow::ensure!(query.state == state, "state mismatch: got state '{}' from query, but expected state was '{}'", query.state, state); 157 | 158 | let client = reqwest::Client::new(); 159 | 160 | println!("Now getting the access token."); 161 | let access_token: AccessToken = client 162 | .post("https://login.live.com/oauth20_token.srf") 163 | .form(&[ 164 | ("client_id", client_id), 165 | ("client_secret", client_secret), 166 | ("code", query.code), 167 | ("grant_type", "authorization_code".to_string()), 168 | ("redirect_uri", redirect_uri.to_string()) 169 | ]) 170 | .send() 171 | .await? 172 | .json() 173 | .await?; 174 | let access_token = access_token.access_token; 175 | let json = serde_json::json!({ 176 | "Properties": { 177 | "AuthMethod": "RPS", 178 | "SiteName": "user.auth.xboxlive.com", 179 | "RpsTicket": format!("d={}", access_token), 180 | }, 181 | "RelyingParty": "http://auth.xboxlive.com", 182 | "TokenType": "JWT" 183 | }); 184 | println!("Now authenticating with Xbox Live."); 185 | let auth_with_xbl: AuthenticateWithXboxLiveOrXsts = client 186 | .post("https://user.auth.xboxlive.com/user/authenticate") 187 | .json(&json) 188 | .send() 189 | .await? 190 | .json() 191 | .await?; 192 | let (token, user_hash) = auth_with_xbl.extract_essential_information()?; 193 | println!("Now getting an Xbox Live Security Token (XSTS)."); 194 | let json = serde_json::json!({ 195 | "Properties": { 196 | "SandboxId": "RETAIL", 197 | "UserTokens": [token] 198 | }, 199 | "RelyingParty": "rp://api.minecraftservices.com/", 200 | "TokenType": "JWT" 201 | }); 202 | let auth_with_xsts: AuthenticateWithXboxLiveOrXsts = client 203 | .post("https://xsts.auth.xboxlive.com/xsts/authorize") 204 | .json(&json) 205 | .send() 206 | .await? 207 | .json() 208 | .await?; 209 | let (token, _) = auth_with_xsts.extract_essential_information()?; 210 | println!("Now authenticating with Minecraft."); 211 | let access_token: AccessToken = client 212 | .post("https://api.minecraftservices.com/authentication/login_with_xbox") 213 | .json(&serde_json::json!({ 214 | "identityToken": format!("XBL3.0 x={};{}", user_hash, token) 215 | })) 216 | .send() 217 | .await? 218 | .json() 219 | .await?; 220 | let access_token = access_token.access_token; 221 | 222 | println!("Checking for game ownership."); 223 | // i don't know how to do signature verification, so we just have to assume the signatures are 224 | // valid :) 225 | let store: Store = client 226 | .get("https://api.minecraftservices.com/entitlements/mcstore") 227 | .bearer_auth(&access_token) 228 | .send() 229 | .await? 230 | .json() 231 | .await?; 232 | 233 | anyhow::ensure!( 234 | store.items.contains(&Item::PRODUCT_MINECRAFT), 235 | "product_minecraft item doesn't exist. do you really own the game?" 236 | ); 237 | 238 | anyhow::ensure!( 239 | store.items.contains(&Item::GAME_MINECRAFT), 240 | "game_minecraft item doesn't exist. do you really own the game?" 241 | ); 242 | 243 | println!("Getting game profile."); 244 | 245 | let profile: Profile = client 246 | .get("https://api.minecraftservices.com/minecraft/profile") 247 | .bearer_auth(&access_token) 248 | .send() 249 | .await? 250 | .json() 251 | .await?; 252 | 253 | println!("Congratulations, you authenticated to minecraft from Rust!"); 254 | println!("access_token={} username={} uuid={}", access_token, profile.name, profile.id); 255 | 256 | Ok(()) 257 | } 258 | --------------------------------------------------------------------------------