nuclearace / SwiftDiscord

Discord API Client for Swift
MIT License
120 stars 25 forks source link

Authentication With OAuth2 Access Token Results in Error #61

Closed Stunner closed 6 years ago

Stunner commented 7 years ago

I have implemented an OAuth flow with https://github.com/p2/OAuth2 and correctly receive an authorization token and refresh token. However, running the following code once:

public func setup(_ accessToken: String) {
    self.client = DiscordClient(token: DiscordToken.init(stringLiteral: accessToken),
                                delegate: self,
                                configuration: [.log(.info)])
    client.connect()
}

Results in the following log to be generated indefinitely:

2017-10-27 04:08:49.387089-0700 MyApp[37061:29258990] LOG: DiscordWebSocketable: Connecting to wss://gateway.discord.gg/?v=6, shard: 0
2017-10-27 04:08:49.387411-0700 MyApp[37061:29258990] LOG: DiscordWebSocketable: Attaching WebSocket, shard: shard: 0
2017-10-27 04:08:49.699006-0700 MyApp[37061:29258990] LOG: DiscordWebSocketable: WebSocket Connected, shard: 0
2017-10-27 04:08:49.699242-0700 MyApp[37061:29258990] LOG: DiscordEngine: Sending handshake, shard: 0
2017-10-27 04:08:49.831020-0700 MyApp[37061:29259498] LOG: DiscordWebSocketable: WebSocket disconnected Optional(Error Domain=WebSocket Code=4004 "Authentication failed." UserInfo={NSLocalizedDescription=Authentication failed.}), shard: 0
2017-10-27 04:08:49.831169-0700 MyApp[37061:29259498] LOG: DiscordEngine: Disconnected, shard: 0
2017-10-27 04:08:49.831338-0700 MyApp[37061:29259498] LOG: DiscordEngine: Already trying to resume or closed, ignoring

Some Google-fu has led me to this: https://github.com/discordapp/discord-api-docs/issues/119

Does this library do what is outlined in the post I have linked above? If not, if you could give me some pointers on where to implement this I would be happy to make an attempt at making a PR for this issue. Thanks.

nuclearace commented 7 years ago

@Stunner Is your accessToken prefixed with Bearer?

Stunner commented 7 years ago

@nuclearace I added that in within the function like so:

public func setup(_ accessToken: String) {
    // please note I have also omitted the space after the 'Bearer' string and same result
    let modifiedAccesstoken = "Bearer " + accessToken 
    self.client = DiscordClient(token: DiscordToken.init(stringLiteral: modifiedAccesstoken),
                                delegate: self,
                                configuration: [.log(.debug)])
    client.connect()
}

But I still get the 4004 authorization failed error.

2017-10-27 21:18:00.561365-0700 MyApp[48201:29721889] DEBUG: shard: 0: Sending ws: {"d":{"compress":false,"large_threshold":250,"token":"Bearer RpfYIW4lVMzwORaEYKztpuiIEBI9mT","properties":{"$referring_domain":"","$os":"iOS","$referrer":"","$browser":"SwiftDiscord","$device":"SwiftDiscord"}},"op":2}
2017-10-27 21:18:00.561365-0700 MyApp[48201:29721889] DEBUG: DiscordWebSocketable: shard: 0 Got text: {"t":null,"s":null,"op":10,"d":{"heartbeat_interval":41250,"_trace":["gateway-prd-main-359x"]}}
2017-10-27 21:18:00.561923-0700 MyApp[48201:29722196] DEBUG: DiscordEngine: Sending heartbeat, shard: 0
2017-10-27 21:18:00.562102-0700 MyApp[48201:29722196] DEBUG: shard: 0: Sending ws: {"d":-1,"op":1}
2017-10-27 21:18:00.679665-0700 MyApp[48201:29721889] LOG: DiscordWebSocketable: WebSocket disconnected Optional(Error Domain=WebSocket Code=4004 "Authentication failed." UserInfo={NSLocalizedDescription=Authentication failed.}), shard: 0

Do you think it could be due to the JSON structure being sent up isn't the same structure as the one defined in the Discord documentation?

{
    "token": "my_token",
    "properties": {
        "$os": "linux",
        "$browser": "disco",
        "$device": "disco"
    },
    "compress": true,
    "large_threshold": 250,
    "shard": [1, 10],
    "presence": {
        "game": {
            "name": "Cards Against Humanity",
            "type": 0
        },
        "status": "dnd",
        "since": 91879201,
        "afk": false
    }
}
Stunner commented 7 years ago

Also, I should add that I tested the authentication token in Postman against the https://discordapp.com/api/users/@me endpoint and it works. Set Authorization to Bearer RpfYIW4lVMzwORaEYKztpuiIEBI9mT and I get back a successful response with data.

(I have modified the access token slightly so as to protect my account identity, but if you would like me to send you the auth token for you to perform tests on your side, I would be happy to send it over via email.)

nuclearace commented 7 years ago

@Stunner If you modify https://github.com/nuclearace/SwiftDiscord/blob/master/Sources/SwiftDiscord/Gateway/DiscordEngine.swift#L52 to add a presence, does it connect?

Stunner commented 7 years ago

@nuclearace Attempted that and took it one step further and modified that bit of code to exactly match what is provided exactly in the example:

Sending ws: {"d":{"shard":[1,10],"presence":{"status":"dnd","game":{"type":0,"name":"Cards Against Humanity"},"since":91879201,"afk":false},"compress":false,"large_threshold":250,"token":"Bearer RpfYIW4lVMzwORaEYKztpuiIEBI9mT","properties":{"$device":"SwiftDiscord","$os":"iOS","$browser":"SwiftDiscord"}},"op":2}

And I still see the exact same error. This portion in the Discord documentation mentions:

The account token sent with your identify payload is incorrect.

I can't imagine that error is accurate as I shouldn't be successfully seeing anything come back from the https://discordapp.com/api/users/@me endpoint with the same token, correct?

nuclearace commented 7 years ago

Well, sending shards with a Bearer token doesn't really make sense.

Stunner commented 7 years ago

Oh, gotcha... I added each field individually and tested and all yielded the same result. Updated to omit shard just now:

Sending ws: {"d":{"presence":{"status":"dnd","game":{"type":0,"name":"Cards Against Humanity"},"since":91879201,"afk":false},"compress":false,"large_threshold":250,"token":"Bearer RpfYIW4lVMzwORaEYKztpuiIEBI9mT","properties":{"$device":"SwiftDiscord","$os":"iOS","$browser":"SwiftDiscord"}},"op":2}

Still see the same 4004 error. :(

nuclearace commented 7 years ago

Hm. I'm not sure. I've never tested the lib with an OAuth token before, and I don't remember seeing any specific things you have to do when authenticating with the gateway with a Bearer token.

nuclearace commented 7 years ago

@Stunner Any luck on this? I haven't had time to look into it.

Stunner commented 7 years ago

@nuclearace Thanks for checking in. So far, no, but I am going to test the same access token with a different library (discord.py is what I have selected). If the access token works with discord.py just fine that means there is an issue with SwiftDiscord. If it still refuses to work, it indicates a problem on Discord’s end. I have tried reaching out to Discord to get technical support, but the support staff merely sent me an invite for the Discord developers Discord server.

But from what I could gather it looks to be mostly 3rd party and open source devs in that server, am I right? Or should I pursue further help from the folks in that server? I don’t want to repeat my question within the #SwiftDiscord channel as it would be redundant. If you have any recommendations on who/where I should post a call for assistance, I’m all ears.

nuclearace commented 7 years ago

@Stunner I'll ask in the DiscordAPI dev channel if there's anything special I should be doing.

Stunner commented 7 years ago

Ok cool. Let me know if you need anything from me. My screen name on Discord is the same here: Stunner, so feel free to tag me if need be.