Coder Social home page Coder Social logo

mc-auth-com / mc-auth Goto Github PK

View Code? Open in Web Editor NEW
26.0 26.0 3.0 2.12 MB

Easily login with your Minecraft account without giving your password or email to strangers – Fully OAuth 2.0 compliant!

Home Page: https://mc-auth.com/

License: GNU Lesser General Public License v3.0

JavaScript 2.18% HTML 30.28% CSS 0.79% PLpgSQL 5.14% TypeScript 60.80% Dockerfile 0.80%
api gdpr login minecraft minecraft-account oauth oauth2 rest restful

mc-auth's People

Contributors

dependabot-preview[bot] avatar dependabot[bot] avatar spraxdev 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

Watchers

 avatar  avatar  avatar

mc-auth's Issues

Think of good Rate-Limits

Especially authentication routes should be protected by rate-limits, for example (but not limited to):

  • Confirm and change of email addresses
  • Login
  • OAuth2.0 App Create/Edit/Image Upload/...
  • Authorization page that gets presented to the user

Maybe even one big rate-limit on the whole page to stop behavior that is totally not friendly or a totally borked bot/crawler.


4c3d3c1

Check OAuth compatibility

Check OAuth compatibility as suggested in #145.
Mc-Auth should be compliant with OAuth2.0 (RFC 6749) but maybe check again?

Anyway I got it to work by building the second Post request manually in python but I suggest you make your Oauth procedure compatible with standardised OauthV2 procedures such as those used in the OauthLib and the postman Oauth feature. That would make increase the usability of your API making it more attractive to work with for developers.

Autofill username box.

Is your feature request related to a problem? Please describe.
My users are getting frustrated having to enter their username

Describe the solution you'd like
It would be very helpful if a query parameter was added (like &username=) to autofill the username input box on the /oAuth2/authorize page.

PKCE - CSRF Protection

PKCE is an extension to the OAuth 2.0 spec designed to combat CSRF (cross-site remote forgery). Originally designed for mobile/single page apps its becoming more and more common in OAuth systems as it provides good additional security.
It's broken down into two steps. (Authorize setup and token verify).

Authorize:
Before the OAuth flow starts, the initiating server generates a random (secure) string (between 43-128 characters, A-Z, a-z, 0-9 and select punctuation). This generated hash is called the "code verifier". The app then hashes the code verifier using SHA256 (plaintext can be used, but it pretty much defeats the purpose) to generate a code challange. The original code verifier is stored on the origin server, not the mc-auth server. (this is the "code challenge"). The code challenge is then base64 url encoded (this could be different from default base64 encode depending on the language being used, idk javascript too well)

The authorize request would now have these additional arguments (for a PKCE request):
code_challange=BASE64_URLENCODED_CODE_CHALLENGE&code_challenge_method=S256

Code challenge method is used to allow origin servers to specify if the challenge has been hashed using SHA256 or if its just plain. (Should always be either: S256 or plain as in spec).

The code challenge used for the authorization would then be stored with generated access code (however the state is currently stored).

Token Verify:
When the access code is being exchanged for a token (where the state is validated) the PKCE should also be validated (if provided). An additional argument code_verifier is sent to the token route. This is the original string used to generate the hash from, meaning the server is able to validate it simply by hashing the provided verifier using the same method used originally (as specified by code_challenge_method) and then comparing it to the stored code_challenge.

Psudocode:

Origin server authorization:


# Before the authorization redirect, generate the code challenge
code_verifier = randomString()
code_challenge = sha256_hash(code_verifier)

# The code verifier is stored to be re-sent in the authorize request
somehow_store_this(code_verifier)

# Add required arguments to authorization redirect URI
redirect = redirect + "&code_challenge=" + base64_urlencode(code_challenge) + "&code_challenge_method=S256"

MC-Auth authorization flow:


# Generate the access code that is returned to the application, storing
# the provided code challenge and code_challenge_method with the code
# (for the token route to verify the state and code_challenge etc)

somehow_store_this(code_challenge)
somehow_store_this(code_challenge_method)

# Redirect back to origin, no additional arguments required.

Origin server token exchange:


# Get the original code_verifier from storage
code_verifier = get_from_storage()

# Add the original verifier as an argument to the token exchange route
# alongside the other arguments such as the code, client_secret etc.
body_arguments["code_verifier"] = code_verifier

# Send the token request
sendRequest("/token", body_arguments)

MC-Auth token exchange:


# Get the original provided code_challenge and the code_code_challenge_method that
# was used to generate the challenge from the authorization request.
original_code_challenge = get_from_storage()
original_code_challenge_method = get_from_storage()

# Get the provided code verifier argument from POST body.
code_verifier = getArguments["code_verifier"]

# If the code was generated using SHA256 hash, we should hash the provided verifier. If not
# just compare the original provided verifier with the now provided verifier (way less secure).
expected = original_code_challenge_method === "R256" ? sha256_hash(code_verifier) : code_verifier;

# Ensure the verifier is as expected.
if (original_code_challenge !== expected) {
   error("invalid code challenge for verifier");
}

Additional info:

The state is limited to 128 characters but server errors when exceeded

Describe the bug
Just received an error log about SQL errors happening in production and it seems like somebody is trying to use an JWT token as state.

So this is report is actually two bugs:

  1. Exceeding the limit causes an server-side error returning an HTTP status code 500
  2. The limit should probably be greater than 128 characters as JWT is a valid use case

Screenshots, Videos, Logs or Errors
Yeah in the error log file, not posting a users redirect URL etc. :p

Additional context

always getting a 400 response on access token post request

I'm trying to integrate your Oauth procedure in my python-flask website using the flask auth client of OauthLib on python3.8. I have made an account under the minecraft user chryonicWolf and I the first part doing a GET https://mc-auth.com/oAuth2/authorize with my client ID goes fine. But trying to do the POST https://mc-auth.com/oAuth2/token always returns :
{ "error": 400, "message": "client_id does not exist or does not match client_secret" }

Things I've tried to do:

  1. Going deeper into the OauthLib to see if they construct the POST request with missing headers and trying to add everything that is described in your documentation.
  2. refreshing the client_secret
  3. Trying to do the entire Oauth2.0 procedure with Postman also gives the same error
  4. Doing the login part with my website and simulating the 2nd part with Postman where I control each aspect of the POST request very closely also doesnt work.

All of this doesn't work and I'm starting to feel it is a problem at your server. Because the first part works so the redirect url and client_id should be ok. I refreshed and checked the client_secret so it also should be correct.

Don't send 'data' when exchanging for a token

I believe this is agains OAuth 2.0 and an /profile route should be used instead, giving the exchanged token an actual purpose.

We'd want to keep the route for backwards compatibility and introduce the 'new' endpoints at the /v2/ suffix.

Heavily refactor code

Quit some time passed on the first lines of code in this repo and I've learned a lot and the code is kinda messy. Not sure if it starten in Vanilla JS and just got ported to TypeScript to 'just work' but seeing the code it just needs some additional work

OpenID

OpenID is another spec optional for OAuth 2.0.

Why should McAuth use/support OpenID?

OAuth and OpenID were created to tackle two similar yet different scenarios. OAuth was created to allow for user authorization, for example the OAuth may allow for the bearer token to access scoped parts of the users account (such as requesting "profile.edit" scope). In this case, you are authorizing an external service to do x on your account.

OpenID instead focuses on user authentication. Instead of asking for permission to interact with a user account, it is simply asking the target application about the users identity (uuid, username in this case).

OpenID Features:

OpenID offers a very large feature set (such as session management etc for federated networks), not all of which I'm suggesting be implemented here. Instead, I am suggesting two main things:

OpenID Configuration Discovery:

OpenID defines an autodiscovery format allowing for applications using OpenID to autoload all required configuration/routes automatically. (This is used by alot of enterprise connections mainly, however it is also becoming more popular as a quick config option).

The route must be /.well-known/openid-configuration and it must return JSON (even in error state).

OpenID User ID:

This is by no means required, however it can be quite useful for single page applications implementing OpenID flow. It essentially returns a hashed id_token that contains the users basic identity (username, uuid in this case, since email can't be gathered) in the token request.

This means that instead of requiring two requests (one to oauth/token to get access token, then to api/profile with token) the info is returned in the first request (oauth/token).

This does however require JWK (JSON Web Keys) certificates to essentially sign each id_token (verifying identity provider authenticity), hence why its not required (since it could be a pain to implement).

Allow for non OAuth2.0 workflow that doesn't require the user to visit a Website

Quote from Discord chat:

well the old system I used it just gave a code when you connected to the server and then that code could be used once to retrieve the users name and uuid from the api
obviously the style of having the website give the code could be technically better since it can remember the login but I really doubt there are many cases where a user has to logon thru the service multiple times within a short time
but obviously even if the url is https://mc-auth.com/whatever discord will pop up that hey are you sure prompt which is the problem with any authentication


I'd like to use the same client_id and client_secret used for OAuth2.0 but instead of pointing the user to Mc-Auth and back to the requesting app.

Instead something like the following:

  1. The app tells me that Minecraft-User SpraxDev wants to authenticate
  2. Mc-Auth sends a success response, maybe with a request/session token and Minecraft server IP to join
  3. The user joins the server and gives the generated Code to the app
  4. The App gives me the request/session token and the code that was provided by the user
  5. Mc-Auth responds with the users profile information or an error

Create example repository

Create an extra repository containing examples in different languages/enviroments

Examples:

  • Node.js
  • PHP
  • Java

Higher test coverage

Unit tests are great. I probably won't aim near 100% coverage but if important modules are covered, I'm happy and don't need to test every feature by hand that might be affected by some changes.

Maybe having mutation tests after or while writing the tests might help in writing better tests.

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.