A Minecraft Fabric mod that connects the game with ATProtocol ⛏️
8
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(server): track OAuth auth type in server-side sessions

- AtProtoSessionManager.PlayerSession: add authType field (oauth/app_password)
- storeVerifiedSession: accept authType parameter
- AuthenticatePacket: include authType in client→server packet
- ServerNetworkHandler: pass authType through to session storage
- AtProtoCommands: display auth type in /atproto whoami output;
update help text to mention OAuth browser login

The server now knows whether a session came from OAuth or app-password
auth, enabling future DPoP-aware request handling on the server side.

👾 Generated with [Letta Code](https://letta.com)

Co-Authored-By: Letta Code <noreply@letta.com>

authored by

Ewan Croft
Letta Code
and committed by
Tangled
7ff1842a e3b20bf2

+30 -13
+11 -2
src/main/kotlin/com/jollywhoppers/atproto/server/AtProtoCommands.kt
··· 324 324 val linkedAgo = formatTimeSince(identity.linkedAt) 325 325 val verifiedAgo = formatTimeSince(identity.lastVerified) 326 326 val isAuthenticated = sessionManager.hasSession(player.uuid) 327 + val session = sessionManager.getAllSessions()[player.uuid] 328 + val authType = session?.authType ?: "none" 327 329 328 330 context.source.sendSuccess( 329 331 { ··· 335 337 .append(Component.literal("\n")) 336 338 .append( 337 339 if (isAuthenticated) { 338 - Component.literal("\n§aAuthentication: §f✓ Active") 340 + val typeLabel = when (authType) { 341 + "oauth" -> "§bOAuth" 342 + else -> "§eApp Password" 343 + } 344 + Component.literal("\n§aAuthentication: §f✓ Active ($typeLabel§f)") 339 345 .append(Component.literal("\n§7You can sync data to AT Protocol")) 340 346 } else { 341 347 Component.literal("\n§cAuthentication: §f✗ Not logged in") ··· 467 473 .append(Component.literal("\n §7Look up another player's AT Protocol identity")) 468 474 .append(Component.literal("\n")) 469 475 .append(Component.literal("\n§e━━━ Client-Side Login (Type in Client) ━━━")) 470 - .append(Component.literal("\n§eFor authentication, use the client-side command:")) 476 + .append(Component.literal("\n§eFor authentication, use the client-side commands:")) 477 + .append(Component.literal("\n§f/atproto login <handle>")) 478 + .append(Component.literal("\n §7OAuth browser login (Recommended!)")) 471 479 .append(Component.literal("\n§f/atproto login <handle> <app-password>")) 480 + .append(Component.literal("\n §7App password login (fallback)")) 472 481 .append(Component.literal("\n§7Authentication happens on your computer")) 473 482 .append(Component.literal("\n§7Your password never goes to the server!")) 474 483 },
+9 -5
src/main/kotlin/com/jollywhoppers/atproto/server/AtProtoSessionManager.kt
··· 50 50 val accessJwt: String, 51 51 val refreshJwt: String, 52 52 val createdAt: Long = System.currentTimeMillis(), 53 - val lastRefreshed: Long = System.currentTimeMillis() 53 + val lastRefreshed: Long = System.currentTimeMillis(), 54 + val authType: String = "app_password", 54 55 ) 55 56 56 57 @Serializable ··· 115 116 /** 116 117 * Stores a verified session that was authenticated client-side. 117 118 * This is the preferred method for storing sessions. 119 + * @param authType "oauth" or "app_password" (default: "app_password") 118 120 */ 119 121 fun storeVerifiedSession( 120 122 uuid: UUID, ··· 122 124 handle: String, 123 125 pdsUrl: String, 124 126 accessJwt: String, 125 - refreshJwt: String 127 + refreshJwt: String, 128 + authType: String = "app_password", 126 129 ) { 127 - logger.info("Storing verified session for player $uuid (${handle})") 128 - 130 + logger.info("Storing verified session for player $uuid (${handle}) via $authType") 131 + 129 132 val session = PlayerSession( 130 133 uuid = uuid.toString(), 131 134 did = did, ··· 134 137 accessJwt = accessJwt, 135 138 refreshJwt = refreshJwt, 136 139 createdAt = System.currentTimeMillis(), 137 - lastRefreshed = System.currentTimeMillis() 140 + lastRefreshed = System.currentTimeMillis(), 141 + authType = authType, 138 142 ) 139 143 140 144 sessions[uuid] = session
+8 -5
src/main/kotlin/com/jollywhoppers/network/AtProtoPackets.kt
··· 32 32 val handle: String, 33 33 val pdsUrl: String, 34 34 val accessJwt: String, 35 - val refreshJwt: String 35 + val refreshJwt: String, 36 + val authType: String = "app_password", 36 37 ) : CustomPacketPayload { 37 38 override fun type(): CustomPacketPayload.Type<out CustomPacketPayload> = TYPE 38 - 39 + 39 40 companion object { 40 - val TYPE: CustomPacketPayload.Type<AuthenticatePacket> = 41 + val TYPE: CustomPacketPayload.Type<AuthenticatePacket> = 41 42 CustomPacketPayload.Type(AUTHENTICATE_C2S_ID) 42 - 43 + 43 44 val CODEC: StreamCodec<FriendlyByteBuf, AuthenticatePacket> = StreamCodec.of( 44 45 { buf, packet -> 45 46 buf.writeUtf(packet.did) ··· 47 48 buf.writeUtf(packet.pdsUrl) 48 49 buf.writeUtf(packet.accessJwt) 49 50 buf.writeUtf(packet.refreshJwt) 51 + buf.writeUtf(packet.authType) 50 52 }, 51 53 { buf -> 52 54 AuthenticatePacket( ··· 54 56 handle = buf.readUtf(), 55 57 pdsUrl = buf.readUtf(), 56 58 accessJwt = buf.readUtf(), 57 - refreshJwt = buf.readUtf() 59 + refreshJwt = buf.readUtf(), 60 + authType = buf.readUtf(), 58 61 ) 59 62 } 60 63 )
+2 -1
src/main/kotlin/com/jollywhoppers/network/ServerNetworkHandler.kt
··· 91 91 handle = packet.handle, 92 92 pdsUrl = packet.pdsUrl, 93 93 accessJwt = packet.accessJwt, 94 - refreshJwt = packet.refreshJwt 94 + refreshJwt = packet.refreshJwt, 95 + authType = packet.authType, 95 96 ) 96 97 97 98 // Link identity if not already linked