Giter Club home page Giter Club logo

drasl's People

Contributors

catfromplan9 avatar evan-goode avatar fridtjof-de avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

drasl's Issues

Default skins/capes

Allow setting a default skin and/or cape for players who have not set one. If ForwardSkins is enabled, forwarded skins should still override the default skin.

  • Tests

Write recipes.md

In addition to configuration.md, recipes.md should contain example configurations for common setups.

  • Common FallbackAPIServers and RegistrationExistingPlayer configs
  • Open/closed registration
  • Completely independent vs. use Mojang fallbacks

Implement admin page

Depends on #16

  • Table of users
    • profile pictures
  • Delete account, lock account, change password, make admin buttons
    • lock account
    • delete account
    • make admin
    • change password

x509: certificate signed by unknown authority

Getting this when running the server:

drasl-drasl-1 | 2023/11/26 10:17:49 Get "https://sessionserver.mojang.com/session/minecraft/hasJoined?serverId=...": x509: certificate signed by unknown authority

Velocity?

Is this compatible with the Velocity proxy?

Cache responses from fallback API servers

Mostly to avoid rate-limiting, we should cache responses from Mojang/Ely.by/whoever's API for a (configurable) short amount of time instead of hitting them over and over.

Use gocache with an in-memory cache? Would rather not bring in redis or memcached.

Cannot op user from a fallback session server

When adding "https://sessionserver.mojang.com" to FallbackSessionServers, the Minecraft server can authenticate both custom Drasl users, and premium Microsoft accounts. The Minecraft server cannot, however, op premium accounts.

This is because when /op (player name) executed, the Minecraft server uses the /profiles/minecraft endpoint of the ServicesServer to determine the UUID of who to make an operator. Adding an option for FallbackServiceServers could enable this to work.

Implement admin accounts and invites

  • Some way to configure initial admin users
    • List of usernames in the TOML file? Maybe, but then adding a new admin requires editing the config and restarting Drasl
    • First created user is an admin?
  • Ability to invite users via 1-time use URL even if open registration is closed
  • Tests
    • RegistrationNewPlayer with invite
    • RegistrationExistingPlayer with invite, skin verification
    • /drasl/admin/new-invite
    • /drasl/admin/delete-invite
    • /drasl/admin
    • /drasl/admin/update-users
    • /drasl/admin/delete-user
    • First user should be admin, any subsequent should not
    • View/edit another user's profile if you're admin, and if you're not you shouldn't be able to

slim variant is not slim

For some reason, the game ignores my skin model setting and assumes every skin is classic.
website-vs-ingame

What I think the problem is

According to this site, /session/minecraft/profile/<uuid> should return something like this:

{
    "id": "<profile identifier>",
    "name": "<player name>",
    "properties": [ 
        {
            "name": "textures",
            "value": "<base64 string>",
            "signature": "<base64 string; signed data using Yggdrasil's private key>" // Only provided if ?unsigned=false is appended to url
        }
    ],
    "profileActions": []
}

And value should decode to something like this:

{
    "timestamp": <java time in ms>,
    "profileId": "<profile uuid>",
    "profileName": "<player name>",
    "signatureRequired": true, // Only present if ?unsigned=false is appended to url
    "textures": {
        "SKIN": {
            "url": "<player skin URL>",
            "metadata": {
                "model": "slim"
            }
        },
        "CAPE": {
            "url": "<player cape URL>"
        }
    }
}

However, my test account returns this:

{
    "timestamp":1701318253009455404,
    "profileId":"418bb580c44045a5bf3996f200b91c57",
    "profileName":"tester",
    "textures":
    {
        "SKIN": 
            {
"url":"https://drasl.localhost.lnet/drasl/texture/skin/676d6f7657076d3ee60f6e2b33e59cbbbb33dc6dbcf5242ccbceebf10773f71d.png",
        "model":
            {
                "string":"slim"
            }
        }
    }
}

There is no "metadata" block.

Please note that I don't know what I'm doing and that this is just a guess.

My setup

OS: Artix Linux
Drasl: 1.0.0 (from the AUR)
Launcher: PollyMC

Option to disable skin/cape upload

There should be an option to disable uploading skins and capes, for instance to force only using ForwardSkins to support vanilla clients.

PaperMC 1.20.2 java.security.SignatureException: Signature length not correct: got 1 but was expecting 512

Server console throwing an error when trying to login:

[00:12:24 INFO]: UUID of player _daemon_process is 42385598-4714-42f0-bc3f-b8f7800fde10
[00:12:24 INFO]: _daemon_process joined the game
[00:12:24 INFO]: _daemon_process[/127.0.0.1:51636] logged in with entity id 380 at ([world]-1.5, 69.0, -7.5)
[00:12:24 ERROR]: Failed to verify Services signature
java.security.SignatureException: Signature length not correct: got 1 but was expecting 512
	at sun.security.rsa.RSASignature.engineVerify(RSASignature.java:213) ~[?:?]
	at java.security.Signature$Delegate.engineVerify(Signature.java:1435) ~[?:?]
	at java.security.Signature.verify(Signature.java:789) ~[?:?]
	at net.minecraft.util.SignatureValidator.verifySignature(SignatureValidator.java:30) ~[paper-1.20.2.jar:git-Paper-318]
	at net.minecraft.util.SignatureValidator.lambda$from$3(SignatureValidator.java:54) ~[paper-1.20.2.jar:git-Paper-318]
	at java.util.stream.MatchOps$1MatchSink.accept(MatchOps.java:90) ~[?:?]
	at java.util.AbstractList$RandomAccessSpliterator.tryAdvance(AbstractList.java:706) ~[?:?]
	at java.util.stream.ReferencePipeline.forEachWithCancel(ReferencePipeline.java:129) ~[?:?]
	at java.util.stream.AbstractPipeline.copyIntoWithCancel(AbstractPipeline.java:527) ~[?:?]
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:513) ~[?:?]
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499) ~[?:?]
	at java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:230) ~[?:?]
	at java.util.stream.MatchOps$MatchOp.evaluateSequential(MatchOps.java:196) ~[?:?]
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234) ~[?:?]
	at java.util.stream.ReferencePipeline.anyMatch(ReferencePipeline.java:632) ~[?:?]
	at net.minecraft.util.SignatureValidator.from(SignatureValidator.java:50) ~[paper-1.20.2.jar:git-Paper-318]
	at net.minecraft.util.SignatureValidator.validate(SignatureValidator.java:23) ~[paper-1.20.2.jar:git-Paper-318]
	at net.minecraft.world.entity.player.ProfilePublicKey$Data.validateSignature(ProfilePublicKey.java:54) ~[?:?]
	at net.minecraft.world.entity.player.ProfilePublicKey.createValidated(ProfilePublicKey.java:26) ~[paper-1.20.2.jar:git-Paper-318]
	at net.minecraft.network.chat.RemoteChatSession$Data.validate(RemoteChatSession.java:40) ~[?:?]
	at net.minecraft.server.network.ServerGamePacketListenerImpl.handleChatSessionUpdate(ServerGamePacketListenerImpl.java:3458) ~[?:?]
	at net.minecraft.network.protocol.game.ServerboundChatSessionUpdatePacket.handle(ServerboundChatSessionUpdatePacket.java:19) ~[paper-1.20.2.jar:git-Paper-318]
	at net.minecraft.network.protocol.game.ServerboundChatSessionUpdatePacket.a(ServerboundChatSessionUpdatePacket.java:9) ~[paper-1.20.2.jar:git-Paper-318]
	at net.minecraft.network.protocol.PacketUtils.lambda$ensureRunningOnSameThread$0(PacketUtils.java:53) ~[?:?]
	at net.minecraft.server.TickTask.run(TickTask.java:18) ~[paper-1.20.2.jar:git-Paper-318]
	at net.minecraft.util.thread.BlockableEventLoop.doRunTask(BlockableEventLoop.java:153) ~[?:?]
	at net.minecraft.util.thread.ReentrantBlockableEventLoop.doRunTask(ReentrantBlockableEventLoop.java:24) ~[?:?]
	at net.minecraft.server.MinecraftServer.doRunTask(MinecraftServer.java:1324) ~[paper-1.20.2.jar:git-Paper-318]
	at net.minecraft.server.MinecraftServer.d(MinecraftServer.java:193) ~[paper-1.20.2.jar:git-Paper-318]
	at net.minecraft.util.thread.BlockableEventLoop.pollTask(BlockableEventLoop.java:126) ~[?:?]
	at net.minecraft.server.MinecraftServer.pollTaskInternal(MinecraftServer.java:1301) ~[paper-1.20.2.jar:git-Paper-318]
	at net.minecraft.server.MinecraftServer.pollTask(MinecraftServer.java:1294) ~[paper-1.20.2.jar:git-Paper-318]
	at net.minecraft.util.thread.BlockableEventLoop.managedBlock(BlockableEventLoop.java:136) ~[?:?]
	at net.minecraft.server.MinecraftServer.waitUntilNextTick(MinecraftServer.java:1272) ~[paper-1.20.2.jar:git-Paper-318]
	at net.minecraft.server.MinecraftServer.runServer(MinecraftServer.java:1160) ~[paper-1.20.2.jar:git-Paper-318]
	at net.minecraft.server.MinecraftServer.lambda$spin$0(MinecraftServer.java:315) ~[paper-1.20.2.jar:git-Paper-318]
	at java.lang.Thread.run(Thread.java:833) ~[?:?]
[00:12:24 INFO]: _daemon_process lost connection: Invalid signature for profile public key.
Try restarting your game.
[00:12:24 INFO]: _daemon_process left the game

Configurable body size limit

For security purposes, there should be a default limit on the size of a request body. Especially for skin/cape upload.

Admins should bypass Allow* settings

Admin users should still be able to set capes/skins and change player names of other users and themselves regardless of the values of AllowChangingPlayerName, AllowSkins, and AllowCapes.

  • Tests
  • Functionality

Address TODOs

  • Log errors from proxy registration server
  • Log errors from fallback skin servers
  • Post-processing of config
  • Proper errors in services.go
  • Test set skin/cape by URL
  • Test skin/cape delete
  • Think of a better way to do anonymous users
    • #28
    • Going to leave TransientUsers undocumented for now and postpone until after 1.0.0
  • Test 1.19 player publickeys
  • Implement name history?
    Skipping this, Mojang has deprecated the name history API: https://help.minecraft.net/hc/en-us/articles/8969841895693-Username-History-API-Removal-FAQ-
  • #31

Case-sensitive usernames are problematic

Player specific commands break if there is for example a "notch" and "Notch" player, aswell as possibly many plugins or mods. Name system should be altered to be case-insensitive (e.g. API query for player "notch" returns the user "Notch" and the name change API reports that "NOTCH" is taken)

API

Drasl should have an API other than the Web UI.

  • Each user gets a random API token that can be invalidated and re-rolled
  • Refactor front.go to share code with API routes
  • Update user's own profile
  • Admin actions: delete user, change password, lock account
  • Create invite
  • Documentation
  • Tests

Drasl webserver doesn't work (Docker)

Hello! I have tried to set up Drasl on my server using Docker, but when I try to access the web UI or even ping the HTTP server it's running on the port is closed. And the thing is that I am not even connecting from the internet, but from my local network. I made sure that the port is accessible from the computer I'm trying to reach the HTTP server from, so I think that it must by an issue with Drasl. According to the logs which I have supplied below the webserver starts normally.

What I have tried to do (but it didn't help)

  • Changing the port
  • Messing with the config
  • Purposefully making the server throw an error to check if it even works (it does btw)

Here is my config file:

# Drasl default config file

# Example: drasl.example.com
Domain = "mcauth.frnsrv.ru"

# Example: My Drasl Instance
InstanceName = "REDACTED"

# Example: My Organization
ApplicationOwner = "REDACTED"

# Example: 127.0.0.1:25585
ListenAddress = "127.0.0.1:15585"

# Example: https://drasl.example.com
BaseURL = "https://mcauth.frnsrv.ru"

# List of usernames who automatically become admins of the Drasl instance
DefaultAdmins = ["GoodGameInfinity"]

# Amount of time until token expires in seconds, example: 604800 (1 week)
TokenExpireSec = 604800

[RegistrationNewPlayer]
Allow = true
AllowChoosingUUID = false
RequireInvite = true

Here are the logs copied from docker:

2023/12/23 20:24:42 Loading config from /etc/drasl/config.toml

2023/12/23 20:24:42 No users found! Here's an invite URL: https://mcauth.frnsrv.ru/drasl/registration?invite=REDACTED

⇨ http server started on 127.0.0.1:15585

Also some info:
I used Portainer to set up the docker container, it publishes the port 15585/TCP and mounts two binds. The Docker image I used is unmojang/drasl:latest from the Docker Hub.

go test fails

root@9box:/home/cat/drasl# go test
{"time":"2023-06-17T23:47:23.575917554-04:00","level":"ERROR","prefix":"echo","file":"main.go","line":"53","message":"code=429, message=Too many requests. Try again later."}
{"time":"2023-06-17T23:47:23.576138652-04:00","level":"ERROR","prefix":"echo","file":"main.go","line":"53","message":"code=429, message=Too many requests. Try again later."}
2023/06/17 23:47:30 Get "publickeys": unsupported protocol scheme ""
{"time":"2023-06-17T23:47:30.064322696-04:00","level":"ERROR","prefix":"echo","file":"main.go","line":"53","message":"code=429, message=Too many requests. Try again later."}
{"time":"2023-06-17T23:47:30.06450828-04:00","level":"ERROR","prefix":"echo","file":"main.go","line":"53","message":"code=429, message=Too many requests. Try again later."}
{"time":"2023-06-17T23:47:30.064564569-04:00","level":"ERROR","prefix":"echo","file":"main.go","line":"53","message":"code=429, message=Too many requests. Try again later."}
--- FAIL: TestAccount (6.99s)
    --- FAIL: TestAccount/Test_/users/profiles/minecraft/:playerName (0.00s)
        account_test.go:62:
                Error Trace:    /home/cat/drasl/account_test.go:62
                Error:          Not equal:
                                expected: 200
                                actual  : 500
                Test:           TestAccount/Test_/users/profiles/minecraft/:playerName
        account_test.go:64:
                Error Trace:    /home/cat/drasl/account_test.go:64
                Error:          Expected nil, but got: &json.SyntaxError{msg:"invalid character 'I' looking for beginning of value", Offset:1}
                Test:           TestAccount/Test_/users/profiles/minecraft/:playerName
        account_test.go:67:
                Error Trace:    /home/cat/drasl/account_test.go:67
                Error:          Not equal:
                                expected: ""
                                actual  : "username"

                                Diff:
                                --- Expected
                                +++ Actual
                                @@ -1 +1 @@
                                -
                                +username
                Test:           TestAccount/Test_/users/profiles/minecraft/:playerName
        account_test.go:72:
                Error Trace:    /home/cat/drasl/account_test.go:72
                Error:          Expected nil, but got: &errors.errorString{s:"record not found"}
                Test:           TestAccount/Test_/users/profiles/minecraft/:playerName
        account_test.go:76:
                Error Trace:    /home/cat/drasl/account_test.go:76
                Error:          Expected nil, but got: &errors.errorString{s:"Invalid ID"}
                Test:           TestAccount/Test_/users/profiles/minecraft/:playerName
    --- FAIL: TestAccount/Test_/profiles/minecraft (0.00s)
        account_test.go:89:
                Error Trace:    /home/cat/drasl/account_test.go:89
                Error:          Not equal:
                                expected: 200
                                actual  : 500
                Test:           TestAccount/Test_/profiles/minecraft
        account_test.go:91:
                Error Trace:    /home/cat/drasl/account_test.go:91
                Error:          Expected nil, but got: &json.SyntaxError{msg:"invalid character 'I' looking for beginning of value", Offset:1}
                Test:           TestAccount/Test_/profiles/minecraft
        account_test.go:96:
                Error Trace:    /home/cat/drasl/account_test.go:96
                Error:          Expected nil, but got: &errors.errorString{s:"record not found"}

Add option for a simple text-based captcha

Something like:
What is 6 × 5?

I'm not interested in implementing any kind of complex, inaccessible captcha like reCaptcha or HCaptcha. If you want to lock down your instance, use invites or RegistrationExistingPlayer with RequireSkinVerification.

Support authlib-injector

Continued from #4

See this comment from the authlib-injector author: elyby/accounts#2 (comment)

  • /authserver/, /sessionserver/ route prefixes (and unsigned query param?)
  • X-Authlib-Injector-API-Location for these routes
  • API root should return JSON metadata
  • Functional tests

Here is the commit where ely.by added support for authlib-injector: elyby/accounts@4856695

Single Sign-on

Hi! I am currently using this behind oauth2-proxy with Keycloak, but would love the ability to integrate directly with OpenID Connect, SAML, or plain old LDAP.

Write at least a couple functional tests for each endpoint

Front end

  • /
  • /drasl/admin
  • /drasl/challenge-skin
  • /drasl/profile
  • /drasl/registration
  • /drasl/admin/delete-invite
  • /drasl/admin/new-invite
  • /drasl/admin/update-users
  • /drasl/delete-user
  • /drasl/login
  • /drasl/logout
  • /drasl/register
  • /drasl/update
  • /drasl/public/*
  • /drasl/texture/cape/*
  • /drasl/texture/skin/*

authlib-injector

  • /authlib-injector

Authenticate

  • /
  • /authenticate
  • /invalidate
  • /refresh
  • /signout
  • /validate

Account

  • /user/security/location
  • /users/profiles/minecraft/:playerName
  • /profiles/minecraft

Session

  • /session/minecraft/hasJoined
  • /session/minecraft/join
  • /session/minecraft/profile/:id

Services

  • /player/attributes
  • /player/certificates
  • /minecraft/profile/capes/active
  • /minecraft/profile/skins/active
  • /minecraft/profile
  • /minecraft/profile/name/:playerName/available"
  • /minecraft/profile/namechange
  • /privacy/blocklist
  • /rollout/v1/msamigration
  • /minecraft/profile/skins
  • /minecraft/profile/name/:playerName
  • /publickeys

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.