mirror of https://github.com/statping/statping
				
				
				
			new custom oAuth authentication method, added "local" auth method as default
							parent
							
								
									202695ba20
								
							
						
					
					
						commit
						08e5d81c3c
					
				| 
						 | 
				
			
			@ -11,6 +11,7 @@
 | 
			
		|||
- Added Google oAuth email/domain user restrictions
 | 
			
		||||
- Modified notifiers to use dereferenced services and failures
 | 
			
		||||
- Added core.Example() function for testing
 | 
			
		||||
- Added Custom oAuth Authentication method
 | 
			
		||||
 | 
			
		||||
# 0.90.55 (06-18-2020)
 | 
			
		||||
- Added 404 page
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -37,6 +37,10 @@
 | 
			
		|||
            <font-awesome-icon :icon="['fab', 'google']" /> Login with Google
 | 
			
		||||
        </a>
 | 
			
		||||
 | 
			
		||||
        <a v-if="oauth && oauth.custom_client_id" @click.prevent="Customlogin" href="#" class="btn btn-block btn-outline-dark">
 | 
			
		||||
            <font-awesome-icon :icon="['fas', 'address-card']" /> Login with {{oauth.custom_name}}
 | 
			
		||||
        </a>
 | 
			
		||||
 | 
			
		||||
    </div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -95,6 +99,9 @@
 | 
			
		|||
        },
 | 
			
		||||
        Googlelogin() {
 | 
			
		||||
          window.location = `https://accounts.google.com/signin/oauth?client_id=${this.oauth.google_client_id}&redirect_uri=${this.core.domain}/oauth/google&response_type=code&scope=https://www.googleapis.com/auth/userinfo.profile+https://www.googleapis.com/auth/userinfo.email`
 | 
			
		||||
        },
 | 
			
		||||
        Customlogin() {
 | 
			
		||||
          window.location = `${this.oauth.custom_endpoint_auth}?client_id=${this.oauth.custom_client_id}&redirect_uri=${this.core.domain}/oauth/custom${this.oauth.custom_scopes !== "" ? "&scope="+this.oauth.custom_scopes : "" }`
 | 
			
		||||
        }
 | 
			
		||||
      }
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -168,6 +168,70 @@
 | 
			
		|||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div class="card text-black-50 bg-white mb-3">
 | 
			
		||||
            <div class="card-header">Custom oAuth Settings</div>
 | 
			
		||||
            <div class="card-body">
 | 
			
		||||
                <div class="form-group row mt-3">
 | 
			
		||||
                    <label for="custom_name" class="col-sm-4 col-form-label">Custom Name</label>
 | 
			
		||||
                    <div class="col-sm-8">
 | 
			
		||||
                        <input v-model="oauth.custom_name" type="text" class="form-control" id="custom_name" required>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="form-group row mt-3">
 | 
			
		||||
                    <label for="custom_client" class="col-sm-4 col-form-label">Client ID</label>
 | 
			
		||||
                    <div class="col-sm-8">
 | 
			
		||||
                        <input v-model="oauth.custom_client_id" type="text" class="form-control" id="custom_client" required>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="form-group row">
 | 
			
		||||
                    <label for="custom_secret" class="col-sm-4 col-form-label">Client Secret</label>
 | 
			
		||||
                    <div class="col-sm-8">
 | 
			
		||||
                        <input v-model="oauth.custom_client_secret" type="text" class="form-control" id="custom_secret" required>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="form-group row">
 | 
			
		||||
                    <label for="custom_endpoint" class="col-sm-4 col-form-label">Auth Endpoint</label>
 | 
			
		||||
                    <div class="col-sm-8">
 | 
			
		||||
                        <input v-model="oauth.custom_endpoint_auth" type="text" class="form-control" id="custom_endpoint" required>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="form-group row">
 | 
			
		||||
                    <label for="custom_endpoint_token" class="col-sm-4 col-form-label">Token Endpoint</label>
 | 
			
		||||
                    <div class="col-sm-8">
 | 
			
		||||
                        <input v-model="oauth.custom_endpoint_token" type="text" class="form-control" id="custom_endpoint_token" required>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="form-group row">
 | 
			
		||||
                    <label for="custom_scopes" class="col-sm-4 col-form-label">Scopes</label>
 | 
			
		||||
                    <div class="col-sm-8">
 | 
			
		||||
                        <input v-model="oauth.custom_scopes" type="text" class="form-control" id="custom_scopes">
 | 
			
		||||
                        <small>Optional comma delimited list of oauth scopes</small>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="form-group row">
 | 
			
		||||
                    <label for="switch-custom-oauth" class="col-sm-4 col-form-label">Enable Custom Login</label>
 | 
			
		||||
                    <div class="col-md-8 col-xs-12 mt-1">
 | 
			
		||||
                    <span @click="custom_enabled = !!custom_enabled" class="switch float-left">
 | 
			
		||||
                        <input v-model="custom_enabled" type="checkbox" class="switch" id="switch-custom-oauth" :checked="custom_enabled">
 | 
			
		||||
                        <label for="switch-custom-oauth"> </label>
 | 
			
		||||
                    </span>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="form-group row">
 | 
			
		||||
                    <label for="slack_callback" class="col-sm-4 col-form-label">Callback URL</label>
 | 
			
		||||
                    <div class="col-sm-8">
 | 
			
		||||
                        <div class="input-group">
 | 
			
		||||
                            <input v-bind:value="`${core.domain}/oauth/custom`" type="text" class="form-control" id="custom_callback" readonly>
 | 
			
		||||
                            <div class="input-group-append copy-btn">
 | 
			
		||||
                                <button @click.prevent="copy(`${core.domain}/oauth/custom`)" class="btn btn-outline-secondary" type="button">Copy</button>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        <button class="btn btn-primary btn-block" @click.prevent="saveOAuth" type="submit" :disabled="loading">
 | 
			
		||||
            <font-awesome-icon v-if="loading" icon="circle-notch" class="mr-2" spin/> Save OAuth Settings
 | 
			
		||||
        </button>
 | 
			
		||||
| 
						 | 
				
			
			@ -191,6 +255,7 @@
 | 
			
		|||
            slack_enabled: false,
 | 
			
		||||
            github_enabled: false,
 | 
			
		||||
            local_enabled: false,
 | 
			
		||||
            custom_enabled: false,
 | 
			
		||||
            loading: false,
 | 
			
		||||
            oauth: {
 | 
			
		||||
              gh_client_id: "",
 | 
			
		||||
| 
						 | 
				
			
			@ -204,7 +269,13 @@
 | 
			
		|||
              slack_client_id: "",
 | 
			
		||||
              slack_client_secret: "",
 | 
			
		||||
              slack_team: "",
 | 
			
		||||
              slack_users: ""
 | 
			
		||||
              slack_users: "",
 | 
			
		||||
              custom_name: "",
 | 
			
		||||
              custom_client_id: "",
 | 
			
		||||
              custom_client_secret: "",
 | 
			
		||||
              custom_endpoint_auth: "",
 | 
			
		||||
              custom_endpoint_token: "",
 | 
			
		||||
              custom_scopes: "",
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
      },
 | 
			
		||||
| 
						 | 
				
			
			@ -214,6 +285,7 @@
 | 
			
		|||
      this.github_enabled = this.has('github')
 | 
			
		||||
      this.google_enabled = this.has('google')
 | 
			
		||||
      this.slack_enabled = this.has('slack')
 | 
			
		||||
      this.custom_enabled = this.has('custom')
 | 
			
		||||
    },
 | 
			
		||||
    methods: {
 | 
			
		||||
      providers() {
 | 
			
		||||
| 
						 | 
				
			
			@ -230,6 +302,9 @@
 | 
			
		|||
        if (this.slack_enabled) {
 | 
			
		||||
          providers.push("slack")
 | 
			
		||||
        }
 | 
			
		||||
        if (this.custom_enabled) {
 | 
			
		||||
          providers.push("custom")
 | 
			
		||||
        }
 | 
			
		||||
        return providers.join(",")
 | 
			
		||||
      },
 | 
			
		||||
        has(val) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,6 +29,8 @@ func oauthHandler(w http.ResponseWriter, r *http.Request) {
 | 
			
		|||
		oauth, err = githubOAuth(r)
 | 
			
		||||
	case "slack":
 | 
			
		||||
		oauth, err = slackOAuth(r)
 | 
			
		||||
	case "custom":
 | 
			
		||||
		oauth, err = customOAuth(r)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,40 @@
 | 
			
		|||
package handlers
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/statping/statping/types/core"
 | 
			
		||||
	"github.com/statping/statping/types/errors"
 | 
			
		||||
	"golang.org/x/oauth2"
 | 
			
		||||
	"net/http"
 | 
			
		||||
	"strings"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func customOAuth(r *http.Request) (*oAuth, error) {
 | 
			
		||||
	auth := core.App.OAuth
 | 
			
		||||
	code := r.URL.Query().Get("code")
 | 
			
		||||
 | 
			
		||||
	scopes := strings.Split(auth.CustomScopes, ",")
 | 
			
		||||
 | 
			
		||||
	config := &oauth2.Config{
 | 
			
		||||
		ClientID:     auth.CustomClientID,
 | 
			
		||||
		ClientSecret: auth.CustomClientSecret,
 | 
			
		||||
		Endpoint: oauth2.Endpoint{
 | 
			
		||||
			AuthURL:  auth.CustomEndpointAuth,
 | 
			
		||||
			TokenURL: auth.CustomEndpointToken,
 | 
			
		||||
		},
 | 
			
		||||
		RedirectURL: core.App.Domain + basePath + "oauth/custom",
 | 
			
		||||
		Scopes:      scopes,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	gg, err := config.Exchange(r.Context(), code)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if !gg.Valid() {
 | 
			
		||||
		return nil, errors.New("oauth token is not valid")
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return &oAuth{
 | 
			
		||||
		Token: gg,
 | 
			
		||||
	}, nil
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -20,6 +20,7 @@ func githubOAuth(r *http.Request) (*oAuth, error) {
 | 
			
		|||
		ClientID:     auth.GithubClientID,
 | 
			
		||||
		ClientSecret: auth.GithubClientSecret,
 | 
			
		||||
		Endpoint:     github.Endpoint,
 | 
			
		||||
		RedirectURL:  core.App.Domain + basePath + "oauth/github",
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	gg, err := config.Exchange(r.Context(), code)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,7 +20,7 @@ func googleOAuth(r *http.Request) (*oAuth, error) {
 | 
			
		|||
		ClientID:     auth.GoogleClientID,
 | 
			
		||||
		ClientSecret: auth.GoogleClientSecret,
 | 
			
		||||
		Endpoint:     google.Endpoint,
 | 
			
		||||
		RedirectURL:  core.App.Domain + "/oauth/google",
 | 
			
		||||
		RedirectURL:  core.App.Domain + basePath + "oauth/google",
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	gg, err := config.Exchange(r.Context(), code)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,6 +28,8 @@ func Samples() error {
 | 
			
		|||
		apiSecret = utils.RandomString(32)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	oauth := OAuth{Providers: "local"}
 | 
			
		||||
 | 
			
		||||
	core := &Core{
 | 
			
		||||
		Name:        utils.Params.GetString("NAME"),
 | 
			
		||||
		Description: utils.Params.GetString("DESCRIPTION"),
 | 
			
		||||
| 
						 | 
				
			
			@ -38,6 +40,7 @@ func Samples() error {
 | 
			
		|||
		Footer:      null.NewNullString(""),
 | 
			
		||||
		MigrationId: utils.Now().Unix(),
 | 
			
		||||
		Language:    utils.Params.GetString("LANGUAGE"),
 | 
			
		||||
		OAuth:       oauth,
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return core.Create()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,18 +43,24 @@ type Core struct {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
type OAuth struct {
 | 
			
		||||
	Providers          string `gorm:"column:oauth_providers;" json:"oauth_providers"`
 | 
			
		||||
	GithubClientID     string `gorm:"column:gh_client_id" json:"gh_client_id"`
 | 
			
		||||
	GithubClientSecret string `gorm:"column:gh_client_secret" json:"gh_client_secret" scope:"admin"`
 | 
			
		||||
	GithubUsers        string `gorm:"column:gh_users" json:"gh_users" scope:"admin"`
 | 
			
		||||
	GithubOrgs         string `gorm:"column:gh_orgs" json:"gh_orgs" scope:"admin"`
 | 
			
		||||
	GoogleClientID     string `gorm:"column:google_client_id" json:"google_client_id"`
 | 
			
		||||
	GoogleClientSecret string `gorm:"column:google_client_secret" json:"google_client_secret" scope:"admin"`
 | 
			
		||||
	GoogleUsers        string `gorm:"column:google_users" json:"google_users" scope:"admin"`
 | 
			
		||||
	SlackClientID      string `gorm:"column:slack_client_id" json:"slack_client_id"`
 | 
			
		||||
	SlackClientSecret  string `gorm:"column:slack_client_secret" json:"slack_client_secret" scope:"admin"`
 | 
			
		||||
	SlackTeam          string `gorm:"column:slack_team" json:"slack_team" scope:"admin"`
 | 
			
		||||
	SlackUsers         string `gorm:"column:slack_users" json:"slack_users" scope:"admin"`
 | 
			
		||||
	Providers           string `gorm:"column:oauth_providers;" json:"oauth_providers"`
 | 
			
		||||
	GithubClientID      string `gorm:"column:gh_client_id" json:"gh_client_id"`
 | 
			
		||||
	GithubClientSecret  string `gorm:"column:gh_client_secret" json:"gh_client_secret" scope:"admin"`
 | 
			
		||||
	GithubUsers         string `gorm:"column:gh_users" json:"gh_users" scope:"admin"`
 | 
			
		||||
	GithubOrgs          string `gorm:"column:gh_orgs" json:"gh_orgs" scope:"admin"`
 | 
			
		||||
	GoogleClientID      string `gorm:"column:google_client_id" json:"google_client_id"`
 | 
			
		||||
	GoogleClientSecret  string `gorm:"column:google_client_secret" json:"google_client_secret" scope:"admin"`
 | 
			
		||||
	GoogleUsers         string `gorm:"column:google_users" json:"google_users" scope:"admin"`
 | 
			
		||||
	SlackClientID       string `gorm:"column:slack_client_id" json:"slack_client_id"`
 | 
			
		||||
	SlackClientSecret   string `gorm:"column:slack_client_secret" json:"slack_client_secret" scope:"admin"`
 | 
			
		||||
	SlackTeam           string `gorm:"column:slack_team" json:"slack_team" scope:"admin"`
 | 
			
		||||
	SlackUsers          string `gorm:"column:slack_users" json:"slack_users" scope:"admin"`
 | 
			
		||||
	CustomName          string `gorm:"column:custom_name" json:"custom_name"`
 | 
			
		||||
	CustomClientID      string `gorm:"column:custom_client_id" json:"custom_client_id"`
 | 
			
		||||
	CustomClientSecret  string `gorm:"column:custom_client_secret" json:"custom_client_secret" scope:"admin"`
 | 
			
		||||
	CustomEndpointAuth  string `gorm:"column:custom_endpoint_auth" json:"custom_endpoint_auth"`
 | 
			
		||||
	CustomEndpointToken string `gorm:"column:custom_endpoint_token" json:"custom_endpoint_token" scope:"admin"`
 | 
			
		||||
	CustomScopes        string `gorm:"column:custom_scopes" json:"custom_scopes"`
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// AllNotifiers contains all the Notifiers loaded
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue