Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat( add OAuth2 support ) #1533

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 154 additions & 0 deletions applications.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
// Discordgo - Discord bindings for Go
// Available at https://github.com/bwmarrin/discordgo

// Copyright 2015-2016 Bruce Marriner <bruce@sqls.net>. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

// This file contains functions related to Discord OAuth2 endpoints

package discordgo

// ------------------------------------------------------------------------------------------------
// Code specific to Discord OAuth2 Applications
// ------------------------------------------------------------------------------------------------

// The MembershipState represents whether the user is in the team or has been invited into it
type MembershipState int

// Constants for the different stages of the MembershipState
const (
MembershipStateInvited MembershipState = 1
MembershipStateAccepted MembershipState = 2
)

// A TeamMember struct stores values for a single Team Member, extending the normal User data - note that the user field is partial
type TeamMember struct {
User *User `json:"user"`
TeamID string `json:"team_id"`
MembershipState MembershipState `json:"membership_state"`
Permissions []string `json:"permissions"`
}

// A Team struct stores the members of a Discord Developer Team as well as some metadata about it
type Team struct {
ID string `json:"id"`
Name string `json:"name"`
Description string `json:"description"`
Icon string `json:"icon"`
OwnerID string `json:"owner_user_id"`
Members []*TeamMember `json:"members"`
}

// Application returns an Application structure of a specific Application
// appID : The ID of an Application
func (s *Session) Application(appID string) (st *Application, err error) {

body, err := s.RequestWithBucketID("GET", EndpointOAuth2Application(appID), nil, EndpointOAuth2Application(""))
if err != nil {
return
}

err = unmarshal(body, &st)
return
}

// Applications returns all applications for the authenticated user
func (s *Session) Applications() (st []*Application, err error) {

body, err := s.RequestWithBucketID("GET", EndpointOAuth2Applications, nil, EndpointOAuth2Applications)
if err != nil {
return
}

err = unmarshal(body, &st)
return
}

// ApplicationCreate creates a new Application
// name : Name of Application / Bot
// uris : Redirect URIs (Not required)
func (s *Session) ApplicationCreate(ap *Application) (st *Application, err error) {

data := struct {
Name string `json:"name"`
Description string `json:"description"`
}{ap.Name, ap.Description}

body, err := s.RequestWithBucketID("POST", EndpointOAuth2Applications, data, EndpointOAuth2Applications)
if err != nil {
return
}

err = unmarshal(body, &st)
return
}

// ApplicationUpdate updates an existing Application
// var : desc
func (s *Session) ApplicationUpdate(appID string, ap *Application) (st *Application, err error) {

data := struct {
Name string `json:"name"`
Description string `json:"description"`
}{ap.Name, ap.Description}

body, err := s.RequestWithBucketID("PUT", EndpointOAuth2Application(appID), data, EndpointOAuth2Application(""))
if err != nil {
return
}

err = unmarshal(body, &st)
return
}

// ApplicationDelete deletes an existing Application
// appID : The ID of an Application
func (s *Session) ApplicationDelete(appID string) (err error) {

_, err = s.RequestWithBucketID("DELETE", EndpointOAuth2Application(appID), nil, EndpointOAuth2Application(""))
if err != nil {
return
}

return
}

// Asset struct stores values for an asset of an application
type Asset struct {
Type int `json:"type"`
ID string `json:"id"`
Name string `json:"name"`
}

// ApplicationAssets returns an application's assets
func (s *Session) ApplicationAssets(appID string) (ass []*Asset, err error) {

body, err := s.RequestWithBucketID("GET", EndpointOAuth2ApplicationAssets(appID), nil, EndpointOAuth2ApplicationAssets(""))
if err != nil {
return
}

err = unmarshal(body, &ass)
return
}

// ------------------------------------------------------------------------------------------------
// Code specific to Discord OAuth2 Application Bots
// ------------------------------------------------------------------------------------------------

// ApplicationBotCreate creates an Application Bot Account
//
// appID : The ID of an Application
//
// NOTE: func name may change, if I can think up something better.
func (s *Session) ApplicationBotCreate(appID string) (st *User, err error) {

body, err := s.RequestWithBucketID("POST", EndpointOAuth2ApplicationsBot(appID), nil, EndpointOAuth2ApplicationsBot(""))
if err != nil {
return
}

err = unmarshal(body, &st)
return
}
File renamed without changes.
4 changes: 4 additions & 0 deletions endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,10 @@ var (
EndpointApplicationRoleConnectionMetadata = func(aID string) string { return EndpointApplication(aID) + "/role-connections/metadata" }

EndpointOAuth2 = EndpointAPI + "oauth2/"
EndpointOAuth2Token = EndpointOAuth2 + "token"
EndpointOAuth2TokenRevoke = EndpointOAuth2Token + "/revoke"
EndpointOAuth2AuthorizationInfo = EndpointOAuth2 + "@me"
EndpointOAuth2Authorize = EndpointDiscord + "oauth2/authorize"
EndpointOAuth2Applications = EndpointOAuth2 + "applications"
EndpointOAuth2Application = func(aID string) string { return EndpointOAuth2Applications + "/" + aID }
EndpointOAuth2ApplicationsBot = func(aID string) string { return EndpointOAuth2Applications + "/" + aID + "/bot" }
Expand Down
77 changes: 77 additions & 0 deletions examples/oauth2/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<img align="right" alt="DiscordGo logo" src="/docs/img/discordgo.svg" width="200">

## DiscordGo OAuth2 Example

This example demonstrates how to utilize DiscordGo to request discord tokens
from the discord oauth2 api using a demo.

**Join [Discord Gophers](https://discord.gg/0f1SbxBZjYoCtNPP)
Discord chat channel for support.**

### Build

This assumes you already have a working Go environment setup and that
DiscordGo is correctly installed on your system.

From within the airhorn example folder, run the command below to compile the
example.

```sh
go build
```

### Usage

```
Usage of ./oauth2
-id string
Client id taken from the Settings>OAuth2 section of your application on the Discord Developer's Portal
-secret string
Client secret taken from the Settings>OAuth2 section of your application on the Discord Developer's Portal
-redirect string
Redirect URI set in Settings>OAuth2 section of your application on the Discord Developers Portal
-scope string
Scope to use for all OAuth2 request made with the demo server
-port int
Port to bind the demo server must be a number between 1 and 65535
-cert string
Full path to an ssl certificate if you wish the server to run in https mode
-key string
Full path to an ssl key if you wish the server to run in https mode
-log bool
Enable loggin response to stdout
```

### Setup

You must have created an application in the [Discord Developer's Portal](https://discord.com/developers/applications)
and have setup the Settings>OAuth2 section there to use the demo server.

You will need to grab both the client id and client secret from that section
as well as register a redirect uri to use in that section.

### Http/s Mode

The demo server will run in http mode unless it is provided with an
ssl certificate and key using the -cert and -key options.

Both should be full path names and the cert file should be the full chain
cert file usually called "fullchain.pem" and not the individual certifcate file.

### Using the demo server

The demo server must be run on the same machine as the redirect uri points to.

Assuming your redirect uri is `https://example.org/signin`:

Go to `https://example.org/signin` and you will be redirected to Discord's
OAuth2 sign in portal. After approving the sign in you will be returned to
the demo server and your access token will be shown.

Go to `https://example.org/signin?cred` and the demo server will obtain the
OAuth2 token for the application's developer. The tokens will be redacted in
the demo server's response but not the stdout log if enabled.

Go to `https://example.org/signin?token=...`, substituting a valid access token
without the `Bearer ` prefix for ..., and the demo server will display the
current authorization info for that access token.
Loading