Skip to content
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
55 changes: 55 additions & 0 deletions examples/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
version: "3.7"

services:
proxy:
image: nginx
volumes:
- ./nginx:/etc/nginx/
ports:
# for https communication
- "443:80"

minio:
image: minio/minio:RELEASE.2020-11-25T22-36-25Z
environment:
MINIO_ACCESS_KEY: test
MINIO_SECRET_KEY: testtest123
command: server /data0 /data1 /data2 /data3

adminio-ui:
container_name: gui
image: rzrbld/adminio-ui:release-1.7
environment:
# you will need to add admnio-api.example.com to you /etc/hosts file to emulate a live service
API_BASE_URL: "https://admnio-api.example.com"
ports:
- 80:80

# the name of this service is needed to set the correct cookie domain
# you will need to change the entry in the nginx.conf file if you want to use another domain
adminio.example.com:
container_name: api
image: adminio:local
build:
dockerfile: Dockerfile.dev
context: ..
environment:
MINIO_ACCESS: test
MINIO_SECRET: testtest123
MINIO_HOST_PORT: minio:9000
ADMINIO_HOST_PORT: 0.0.0.0:8080
ADMINIO_OAUTH_ENABLE: "true"
# configuration to use your custom Oauth provider, located at auth.example.com
ADMINIO_OAUTH_PROVIDER: auth0
ADMINIO_OAUTH_CUSTOM_DOMAIN: auth.example.com/oauth
MINIO_OAUTH_SERVER_DOMAIN: auth.example.com/oauth
ADMINIO_OAUTH_CALLBACK: https://adminio-api.example.com/auth/callback
ADMINIO_OAUTH_CLIENT_ID: your_id
ADMINIO_OAUTH_CLIENT_SECRET: your_secret
# variables used in file auth0/auth0.go
MINIO_OAUTH_TOKEN_PATH: "/token"
MINIO_OAUTH_AUTHORIZE_PATH: "/oauth/authorize"
MINIO_OAUTH_TOKEN_INFO_PATH: "/token/info"
ports:
# port exposed for http communication
- 90:8080
24 changes: 24 additions & 0 deletions examples/nginx/localhost.crt
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
-----BEGIN CERTIFICATE-----
MIIEDTCCAvWgAwIBAgIJAMJbEfOkofPkMA0GCSqGSIb3DQEBCwUAMIGcMQswCQYD
VQQGEwJERTEPMA0GA1UECBMGQmVybGluMQ8wDQYDVQQHEwZCZXJsaW4xFzAVBgNV
BAoTDmVuZXJnZW5vdXMgR2JSMRQwEgYDVQQLEwtlbmVyZ2VuaW91czEXMBUGA1UE
AxMOZW5lcmdlbmlvdXMuZXUxIzAhBgkqhkiG9w0BCQEWFGFkbWluQGVuZXJnZW5p
b3VzLmV1MB4XDTE5MDkyOTE4MjQxM1oXDTIwMDkyODE4MjQxM1owgZwxCzAJBgNV
BAYTAkRFMQ8wDQYDVQQIEwZCZXJsaW4xDzANBgNVBAcTBkJlcmxpbjEXMBUGA1UE
ChMOZW5lcmdlbm91cyBHYlIxFDASBgNVBAsTC2VuZXJnZW5pb3VzMRcwFQYDVQQD
Ew5lbmVyZ2VuaW91cy5ldTEjMCEGCSqGSIb3DQEJARYUYWRtaW5AZW5lcmdlbmlv
dXMuZXUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs9GtXWq306m6V
PhryN0LcbDxRYLWIOoehFiAshduLvl2wcE55Js4iLxY5TS5S3Cu5t6u7cMXWWACd
I5HY3alKLd3QasrT7WIGMhEKy5nVJYaSYb88b9yGGoj+vB/d9eGqQavElGRKE9Cn
amocc+j2C2YRxZaYGBHs+B1Mz5oLvJrUOFl/pkFUizY+B64ssJTvOdISNk+jKLlh
JVgCX4yzi7LwUJV3NiMbQbUOPwHzjppH0FrIoMn99dRDcrBUi/cz53HZTa3P/F9Y
0hXk+3914fIICbtn4vUV29UJQkBifyww9xxmFZlMMJt+5wCiZGcQKH51tsY09t86
QX2PC+fNAgMBAAGjUDBOMB0GA1UdDgQWBBRRv0upoPrZvXuVzJ4wnNOCTyHmVzAf
BgNVHSMEGDAWgBRRv0upoPrZvXuVzJ4wnNOCTyHmVzAMBgNVHRMEBTADAQH/MA0G
CSqGSIb3DQEBCwUAA4IBAQBesYfaPRpzmUkwv/zDyWraNqkjHL6PuhSAXnNVf+1V
jbKqzl3ksH/sHxsc43KZ/RT6Y4zOnwKsjQJ9bAqMAPdVwXtbmWkv6tIG4FN7cxoH
eR0RFDakGgsuafBHjhVp310c9glhiSAl6vQ8ffy4t4ycyRj7yemljoORhv5X5XsP
NY3T4XV7S01lAeBNikw1j1qMS3JSza6VoeP/rk5w5aveOGJDtc+Kj0K9FdjHAeEg
K68SJeHU9zeGHVJm8PcGk4i7GWVIUm2PpXO+14TXHhSMv4jNd2sn5mdATxa9vhHZ
Asj2/vCwtzzi9rzgVwOpCdvNaLNjot6fI4aGbzR6eJrL
-----END CERTIFICATE-----
28 changes: 28 additions & 0 deletions examples/nginx/localhost.key
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
-----BEGIN PRIVATE KEY-----
MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQCs9GtXWq306m6V
PhryN0LcbDxRYLWIOoehFiAshduLvl2wcE55Js4iLxY5TS5S3Cu5t6u7cMXWWACd
I5HY3alKLd3QasrT7WIGMhEKy5nVJYaSYb88b9yGGoj+vB/d9eGqQavElGRKE9Cn
amocc+j2C2YRxZaYGBHs+B1Mz5oLvJrUOFl/pkFUizY+B64ssJTvOdISNk+jKLlh
JVgCX4yzi7LwUJV3NiMbQbUOPwHzjppH0FrIoMn99dRDcrBUi/cz53HZTa3P/F9Y
0hXk+3914fIICbtn4vUV29UJQkBifyww9xxmFZlMMJt+5wCiZGcQKH51tsY09t86
QX2PC+fNAgMBAAECggEAJMnIm0gagGHtK6mOKb8/ZYtQOS8M7fElMEp4hX/jdxIC
86ivyG1Mo1DItV+JXu6eDl7XFIOkUTdeyg3q0+oyPCkNaWuNwQ5ZL2Au59Du47ub
qD9KYhyZF51FTonNbXUDjydw1duKiYc1dqbX8z1kbBF4oIcaxTc5eOI9uTzfU2dt
LDybIc4IQbb01beGvpeBLnygDnXm3FkEDfR2XUV0g0xUyKDQe5xqeDx8Bmf+LvQX
ArtkvRgCLRAwuTrCFWaf3e9osLwTMFYD/UFBBluSUc00Efb0U6symtQAgd8ZAzdG
wviAm6ka+rJdpUgr9eOIiiPP5JAxTudadZQcIZZ9sQKBgQDXxzuRoI/KWqFWARMz
fmEXOTy4m6LfiwMArr31rP354YfWbWVOtQcvrabKnF04WzVauXZSrWKC8bJpQue3
WDLVvZISlcCC3q7jCxqIcM7vpi6wyyg7mYmC2gQCh5Wbm2T0ehxsbjD9lWVCxCg4
B6OWr47daw9k7EBNJjpg/DL94wKBgQDNMa8AK1DAleDw08HI8qiGottDIWcLkBsi
3LS6q9gZ9/op2D9dcvrB+qm/3Bn4xjfJ+NI32E9CeU32i65kTfJXE3kGOwQrq2wc
hzYm1y8ezuakDb0rSBPXDc+Ipa0IDM717arM+yrJCoLpOikzcpTEqrZjHCKbjXUY
RK7biEtyjwKBgQCfYbJGZurO9RKmjDS6nGbq2IRZd9xecjfNkUUO6rDOmh/T6woh
kOW1+fZxQf45WmWWldcoSpmxTwYRajHt41/pMRVsVODVydY0Lkdy8KBps75ZKDaX
j1lbJd5AYBXJ0oZHbsr/7ISTSn55SprKiBn1e8dzFVlRmpAEbHBCowanMQKBgQCT
Uw7A4liyTWoZvxAthPw23orq4fqoNKknGKuyM1uPGZpFnPuxzrH3wE9Mb20+TqMT
olDcw7P0mD+/un5VihlrJ5IHRSwzZnrS6MmajXlJd2flde/SOYf1KfdNtxZK51dY
/3FYhyUq/x8K8TVPuP7TTXZyJms6oA/ogrfA61SwRQKBgGa0hOsKoMnfdxt99sGf
ZX1YY7UXuUmHBArNFoDd1krmX+315O3+dM8Dfqn+TRtlVMXHyq3dfAsUNqt0C9/q
XDhGUG6bKjBawVvACyZ494Bhut7i9nOD2CcIvNvJYHJWZ7kF452PpRZ6b3Me0T81
EadZPQO3mBxk9BXLffQRuPVB
-----END PRIVATE KEY-----
26 changes: 26 additions & 0 deletions examples/nginx/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
user nginx;

events {
worker_connections 1024;
}

worker_processes 1;

http {

keepalive_timeout 65;

server {
listen 80 ssl;
server_name localhost;

ssl_certificate /etc/nginx/localhost.crt;
ssl_certificate_key /etc/nginx/localhost.key;

access_log /var/log/nginx/example.log;

location / {
proxy_pass http://admnio.example.com:8080/;
}
}
}
201 changes: 201 additions & 0 deletions src/auth0/auth0.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,201 @@
// taken from : https://github.com/markbates/goth/blob/master/providers/auth0/auth0.go
// Package auth0 implements the OAuth2 protocol for authenticating users through uber.
// This package can be used as a reference implementation of an OAuth2 provider for Goth.
package auth0

import (
"bytes"
"encoding/json"
"io"
"fmt"
"net/http"
"github.com/markbates/goth"
"golang.org/x/oauth2"
// TODO: this function could be imported instead of being redefined
// getEnv "github.com/rzrbld/adminio-api/config"
"os"
)

const (
protocol string = "https://"
)

var (
tokenEndpoint = getEnv("MINIO_OAUTH_TOKEN_PATH", "/oauth/token")
authEndpoint = getEnv("MINIO_OAUTH_AUTHORIZE_PATH", "/authorize")
endpointProfile = getEnv("MINIO_OAUTH_TOKEN_INFO_PATH", "/userinfo")
customDomain = getEnv("MINIO_OAUTH_SERVER_DOMAIN", "auth0.com/oauth")
)

func getEnv(key, fallback string) string {
value, exist := os.LookupEnv(key)

if !exist {
return fallback
}

return value
}

// Provider is the implementation of `goth.Provider` for accessing Auth0.
type Provider struct {
ClientKey string
Secret string
CallbackURL string
Domain string
HTTPClient *http.Client
config *oauth2.Config
providerName string
}

type auth0UserResp struct {
Name string `json:"name"`
NickName string `json:"nickname"`
Email string `json:"email"`
UserID string `json:"sub"`
AvatarURL string `json:"picture"`
}

// New creates a new Auth0 provider and sets up important connection details.
// You should always call `auth0.New` to get a new provider. Never try to
// create one manually.
func New(clientKey, secret, callbackURL string, auth0Domain string, scopes ...string) *Provider {
p := &Provider{
ClientKey: clientKey,
Secret: secret,
CallbackURL: callbackURL,
Domain: auth0Domain,
providerName: "auth0",
}
p.config = newConfig(p, scopes)
return p
}

// Name is the name used to retrieve this provider later.
func (p *Provider) Name() string {
return p.providerName
}

// SetName is to update the name of the provider (needed in case of multiple providers of 1 type)
func (p *Provider) SetName(name string) {
p.providerName = name
}

func (p *Provider) Client() *http.Client {
return goth.HTTPClientWithFallBack(p.HTTPClient)
}

// Debug is a no-op for the auth0 package.
func (p *Provider) Debug(debug bool) {}

// BeginAuth asks Auth0 for an authentication end-point.
func (p *Provider) BeginAuth(state string) (goth.Session, error) {
return &Session{
AuthURL: p.config.AuthCodeURL(state),
}, nil
}

// FetchUser will go to Auth0 and access basic information about the user.
// the full response will be included in RawData
// https://auth0.com/docs/api/authentication#get-user-info

func (p *Provider) FetchUser(session goth.Session) (goth.User, error) {
s := session.(*Session)
user := goth.User{
AccessToken: s.AccessToken,
Provider: p.Name(),
RefreshToken: s.RefreshToken,
ExpiresAt: s.ExpiresAt,
}


if user.AccessToken == "" {
// data is not yet retrieved since accessToken is still empty
return user, fmt.Errorf("%s cannot get user information without accessToken", p.providerName)
}

userProfileURL := protocol + customDomain + endpointProfile
req, err := http.NewRequest("GET", userProfileURL, nil)
if err != nil {
return user, err
}
req.Header.Set("Authorization", "Bearer "+s.AccessToken)
resp, err := p.Client().Do(req)
if err != nil {
if resp != nil {
resp.Body.Close()
}
return user, err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
return user, fmt.Errorf("%s responded with a %d trying to fetch user information", p.providerName, resp.StatusCode)
}

err = userFromReader(resp.Body, &user)
return user, err
}

func newConfig(provider *Provider, scopes []string) *oauth2.Config {
c := &oauth2.Config{
ClientID: provider.ClientKey,
ClientSecret: provider.Secret,
RedirectURL: provider.CallbackURL,
Endpoint: oauth2.Endpoint{
AuthURL: protocol + customDomain + authEndpoint,
TokenURL: protocol + customDomain + tokenEndpoint,
},
Scopes: []string{},
}

if len(scopes) > 0 {
for _, scope := range scopes {
c.Scopes = append(c.Scopes, scope)
}
} else {
c.Scopes = append(c.Scopes, "profile", "openid")
}

return c
}

func userFromReader(r io.Reader, user *goth.User) error {
var rawData map[string]interface{}

buf := new(bytes.Buffer)
buf.ReadFrom(r)
err := json.Unmarshal(buf.Bytes(), &rawData)
if err != nil {
return err
}

u := auth0UserResp{}
err = json.Unmarshal(buf.Bytes(), &u)
if err != nil {
return err
}
user.Email = u.Email
user.Name = u.Name
user.NickName = u.NickName
user.UserID = u.UserID
user.AvatarURL = u.AvatarURL
user.RawData = rawData
return nil
}

//RefreshTokenAvailable refresh token is provided by auth provider or not
func (p *Provider) RefreshTokenAvailable() bool {
return true
}

//RefreshToken get new access token based on the refresh token
func (p *Provider) RefreshToken(refreshToken string) (*oauth2.Token, error) {
token := &oauth2.Token{RefreshToken: refreshToken}
ts := p.config.TokenSource(oauth2.NoContext, token)
newToken, err := ts.Token()
if err != nil {
return nil, err
}
return newToken, err
}
Loading