Skip to content
This repository was archived by the owner on Mar 27, 2025. It is now read-only.
Merged
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
2 changes: 1 addition & 1 deletion .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ run:
- validate.go

linters:
enable-all: true
enable-all: false
disable:
- prealloc
- dupl
81 changes: 81 additions & 0 deletions auth/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,87 @@ import (
"github.com/pkg/errors"
)

type DeviceCode struct {
DeviceCode string `json:"device_code"`
UserCode string `json:"user_code"`
VerificationURI string `json:"verification_uri"`
ExpiresIn int `json:"expires_in"`
Interval int `json:"interval"`
VerificationURIComplete string `json:"verification_uri_complete"`
}

func StartDeviceAuth(authURL, clientID string) (data DeviceCode, err error) {
url := authURL + "/oauth/device/code"

payload := strings.NewReader("client_id=" + clientID + "&audience=https://api.arduino.cc")

req, err := http.NewRequest("POST", url, payload)
if err != nil {
return data, err
}

req.Header.Add("content-type", "application/x-www-form-urlencoded")

res, err := http.DefaultClient.Do(req)
if err != nil {
return data, err
}

defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return data, err
}

err = json.Unmarshal(body, &data)
if err != nil {
return data, err
}

return data, nil
}

func CheckDeviceAuth(authURL, clientID, deviceCode string) (token string, err error) {
url := authURL + "/oauth/token"

payload := strings.NewReader("grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code&device_code=" + deviceCode + "&client_id=" + clientID)

req, err := http.NewRequest("POST", url, payload)
if err != nil {
return token, err
}

req.Header.Add("content-type", "application/x-www-form-urlencoded")

res, err := http.DefaultClient.Do(req)
if err != nil {
return token, err
}

defer res.Body.Close()
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return token, err
}

if res.StatusCode != 200 {
return token, errors.New(string(body))
}

data := struct {
AccessToken string `json:"access_token"`
ExpiresIn int `json:"expires_in"`
TokenType string `json:"token_type"`
}{}

err = json.Unmarshal(body, &data)
if err != nil {
return token, err
}

return data.AccessToken, nil
}

// Config contains the variables you may want to change
type Config struct {
// CodeURL is the endpoint to redirect to obtain a code
Expand Down
41 changes: 38 additions & 3 deletions install.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ package main

import (
"bytes"
"context"
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
Expand All @@ -40,7 +41,7 @@ import (
"time"

"github.com/arduino/arduino-connector/auth"
"github.com/eclipse/paho.mqtt.golang"
mqtt "github.com/eclipse/paho.mqtt.golang"
"github.com/facchinm/service"
"github.com/kardianos/osext"
"github.com/pkg/errors"
Expand All @@ -64,8 +65,8 @@ func register(config Config, configFile, token string) {
// Request token
var err error
if token == "" {
token, err = askCredentials(config.AuthURL)
check(err, "AskCredentials")
token, err = deviceAuth(config.AuthURL, config.AuthClientID)
check(err, "deviceAuth")
}

// Generate a Private Key and CSR
Expand Down Expand Up @@ -142,6 +143,40 @@ func registerDeviceViaMQTT(config Config) {

}

// Implements Auth0 device authentication flow: https://auth0.com/docs/flows/guides/device-auth/call-api-device-auth
func deviceAuth(authURL, clientID string) (token string, err error) {
code, err := auth.StartDeviceAuth(authURL, clientID)
if err != nil {
return "", err
}

fmt.Printf("Go to %s and confirm authentication\n", code.VerificationURIComplete)

ticker := time.NewTicker(10 * time.Second)

ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)

// Loop until the user authenticated or the timeout hits
Loop:
for {
select {
case <-ctx.Done():
break Loop
case <-ticker.C:
var err error
token, err = auth.CheckDeviceAuth(authURL, clientID, code.DeviceCode)
if err == nil {
cancel()
}
}
}

ticker.Stop()
cancel()

return token, nil
}

func askCredentials(authURL string) (token string, err error) {
var user, pass string
fmt.Println("Insert your arduino username")
Expand Down
16 changes: 13 additions & 3 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ import (
"time"

docker "github.com/docker/docker/client"
"github.com/eclipse/paho.mqtt.golang"
mqtt "github.com/eclipse/paho.mqtt.golang"
"github.com/fsnotify/fsnotify"
"github.com/hpcloud/tail"
"github.com/namsral/flag"
Expand Down Expand Up @@ -59,6 +59,7 @@ type Config struct {
HTTPSProxy string
ALLProxy string
AuthURL string
AuthClientID string
APIURL string
updateURL string
appName string
Expand All @@ -76,6 +77,7 @@ func (c Config) String() string {
out += "https_proxy=" + c.HTTPSProxy + "\r\n"
out += "all_proxy=" + c.ALLProxy + "\r\n"
out += "authurl=" + c.AuthURL + "\r\n"
out += "auth_client_id=" + c.AuthClientID + "\r\n"
out += "apiurl=" + c.APIURL + "\r\n"
out += "cert_path=" + c.CertPath + "\r\n"
out += "sketches_path=" + c.SketchesPath + "\r\n"
Expand Down Expand Up @@ -108,7 +110,7 @@ func main() {
flag.StringVar(&config.HTTPProxy, "http_proxy", "", "URL of HTTP proxy to use")
flag.StringVar(&config.HTTPSProxy, "https_proxy", "", "URL of HTTPS proxy to use")
flag.StringVar(&config.ALLProxy, "all_proxy", "", "URL of SOCKS proxy to use")
flag.StringVar(&config.AuthURL, "authurl", "https://hydra.arduino.cc", "Url of authentication server")
flag.StringVar(&config.AuthURL, "authurl", "https://login.arduino.cc", "Url of authentication server")
flag.StringVar(&config.APIURL, "apiurl", "https://api2.arduino.cc", "Url of api server")
flag.BoolVar(&config.CheckRoFs, "check_ro_fs", false, "Check for Read Only file system and remount if necessary")
flag.BoolVar(&debugMqtt, "debug-mqtt", false, "Output all received/sent messages")
Expand All @@ -117,6 +119,14 @@ func main() {

flag.Parse()

if config.AuthURL == "https://login.oniudra.cc" {
config.AuthClientID = "ks1R298bA8IQnG4p6dPlbdEIXF6Kt1Lu"
}

if config.AuthURL == "https://login.arduino.cc" {
config.AuthClientID = "QGdLCWFA4uQdbRE2NOFhUI8bnXWMZhCK"
}

if *configFile == "" {
*configFile = defaultConfigFile
}
Expand All @@ -128,7 +138,7 @@ func main() {
check(err, "CreateService")

if *doLogin {
token, err := askCredentials(config.AuthURL)
token, err := deviceAuth(config.AuthURL, config.AuthClientID)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
Expand Down