1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
|
// SPDX-License-Identifier: GPL-3.0-only
// SPDX-FileCopyrightText: 2026 Project Tick
// SPDX-FileContributor: Project Tick Team
/*
* ProjT Launcher - Minecraft Launcher
* Copyright (C) 2026 Project Tick
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#pragma once
#include <QByteArray>
#include <QDateTime>
#include <QMap>
#include <QString>
#include <QVariantMap>
namespace projt::minecraft::auth
{
/**
* Validity state for tokens and data.
*/
enum class TokenValidity
{
None, ///< Not validated or expired
Assumed, ///< Assumed valid (e.g., loaded from disk)
Certain ///< Verified valid by server
};
/**
* Generic OAuth/authentication token.
*/
struct AuthToken
{
QDateTime issuedAt; ///< When the token was issued
QDateTime expiresAt; ///< When the token expires
QString accessToken; ///< The access token value
QString refreshToken; ///< OAuth refresh token (if applicable)
QVariantMap metadata; ///< Additional token data (e.g., user hash)
TokenValidity validity = TokenValidity::None;
bool persist = true; ///< Whether to save this token to disk
[[nodiscard]] bool isExpired() const noexcept
{
return expiresAt.isValid() && QDateTime::currentDateTimeUtc() >= expiresAt;
}
[[nodiscard]] bool hasRefreshToken() const noexcept
{
return !refreshToken.isEmpty();
}
};
/**
* Minecraft player skin data.
*/
struct PlayerSkin
{
QString id;
QString url;
QString variant; ///< "CLASSIC" or "SLIM"
QByteArray imageData;
[[nodiscard]] bool isEmpty() const noexcept
{
return id.isEmpty();
}
};
/**
* Minecraft player cape data.
*/
struct PlayerCape
{
QString id;
QString url;
QString alias;
QByteArray imageData;
[[nodiscard]] bool isEmpty() const noexcept
{
return id.isEmpty();
}
};
/**
* Minecraft game entitlements (ownership info).
*/
struct GameEntitlements
{
bool ownsMinecraft = false;
bool canPlayMinecraft = false;
TokenValidity validity = TokenValidity::None;
[[nodiscard]] bool isValid() const noexcept
{
return validity != TokenValidity::None;
}
};
/**
* Minecraft Java Edition profile.
*/
struct MinecraftJavaProfile
{
QString id; ///< UUID without dashes
QString name; ///< Player name (gamertag)
PlayerSkin skin;
QString activeCapeId;
QMap<QString, PlayerCape> capes;
TokenValidity validity = TokenValidity::None;
[[nodiscard]] bool hasProfile() const noexcept
{
return !id.isEmpty();
}
[[nodiscard]] bool hasName() const noexcept
{
return !name.isEmpty();
}
};
/**
* Account type enumeration.
*/
enum class AccountKind
{
Microsoft, ///< Microsoft/Xbox Live authenticated
Offline ///< Offline mode (no authentication)
};
/**
* Account status enumeration.
*/
enum class AccountStatus
{
Unchecked, ///< Not yet validated
Offline, ///< Network unavailable
Working, ///< Auth in progress
Online, ///< Fully authenticated
Disabled, ///< Disabled (e.g., client ID mismatch)
Error, ///< Error state
Expired, ///< Tokens expired, needs refresh
Gone ///< Account no longer exists
};
/**
* Complete authentication credentials for a Minecraft account.
*
* This structure holds all tokens and profile information needed to
* authenticate and play Minecraft. It is passed by reference to Step
* implementations which populate fields as authentication progresses.
*/
struct Credentials
{
// === Account identification ===
AccountKind kind = AccountKind::Microsoft;
QString internalId; ///< Internal account identifier
QString msaClientId; ///< Microsoft Application client ID used
// === Microsoft authentication chain ===
AuthToken msaToken; ///< Microsoft OAuth token
AuthToken xboxUserToken; ///< XBL user token
AuthToken xboxServiceToken; ///< XSTS token for Xbox services
AuthToken minecraftServicesToken; ///< XSTS token for Minecraft services
// === Minecraft authentication ===
AuthToken minecraftAccessToken; ///< Yggdrasil-style access token
MinecraftJavaProfile profile; ///< Player profile
GameEntitlements entitlements; ///< Game ownership
// === Runtime state (not persisted) ===
AccountStatus status = AccountStatus::Unchecked;
QString lastError;
// === Convenience accessors ===
/**
* Display string for this account (gamertag or profile name).
*/
[[nodiscard]] QString displayName() const noexcept
{
return profile.hasName() ? profile.name : QStringLiteral("(unknown)");
}
/**
* Access token to pass to the game.
*/
[[nodiscard]] QString accessToken() const noexcept
{
return minecraftAccessToken.accessToken;
}
/**
* Profile UUID for game launch.
*/
[[nodiscard]] QString profileId() const noexcept
{
return profile.id;
}
/**
* Profile name for game launch.
*/
[[nodiscard]] QString profileName() const noexcept
{
return profile.name;
}
/**
* Xbox user hash (uhs) from token metadata.
*/
[[nodiscard]] QString xboxUserHash() const noexcept
{
return xboxUserToken.metadata.value(QStringLiteral("uhs")).toString();
}
};
} // namespace projt::minecraft::auth
|