Skip to content

Commit

Permalink
Merge pull request #1 from AzureAD/device-code-sample
Browse files Browse the repository at this point in the history
Refactored and fixed device code sample
  • Loading branch information
hchittanuru3 authored Jun 15, 2020
2 parents a01d22e + 5af4868 commit ee1f38a
Show file tree
Hide file tree
Showing 44 changed files with 394 additions and 252 deletions.
48 changes: 48 additions & 0 deletions examples/DeviceCodeFlowSample.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

package main

import (
"context"
"fmt"
"time"

msalgo "github.com/AzureAD/microsoft-authentication-library-for-go/src/msal"
log "github.com/sirupsen/logrus"
)

func deviceCodeCallback(deviceCodeResult msalgo.IDeviceCodeResult) {
log.Infof(deviceCodeResult.GetMessage())
}

func setCancelTimeout(seconds int, cancelChannel chan bool) {
time.Sleep(time.Duration(seconds) * time.Second)
cancelChannel <- true
}

func acquireTokenDeviceCode() {
cancelTimeout := 100 //Change this for cancel timeout
config := CreateConfig("config.json")
pcaParams := createPCAParams(config.GetClientID(), config.GetAuthority())
publicClientApp, err := msalgo.CreatePublicClientApplication(pcaParams)
if err != nil {
log.Fatal(err)
}
cancelCtx, cancelFunc := context.WithTimeout(context.Background(), time.Duration(cancelTimeout)*time.Second)
defer cancelFunc()
deviceCodeParams := msalgo.CreateAcquireTokenDeviceCodeParameters(cancelCtx, config.GetScopes(), deviceCodeCallback)
resultChannel := make(chan msalgo.IAuthenticationResult)
errChannel := make(chan error)
go func() {
result, err := publicClientApp.AcquireTokenByDeviceCode(deviceCodeParams)
errChannel <- err
resultChannel <- result
}()
err = <-errChannel
if err != nil {
log.Fatal(err)
}
result := <-resultChannel
fmt.Println("Access token is " + result.GetAccessToken())
}
18 changes: 18 additions & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Running Examples for MSAL Go

To run one of the examples of uses of MSAL Go, you need to first create a `config.json` file. The `config.json` file should look like the following:
```json
{
"authority": "https://login.microsoftonline.com/organizations",
"client_id": "your_client_id",
"scopes": ["user.read"],
// You can find the other permission names from this document
// https://docs.microsoft.com/en-us/graph/permissions-reference
"username": "your_username",
"password": "your_password" //This is a sample only. DO NOT persist your password.
}
```

To run one of the examples, run the command `go run src/examples/*.go <example-arg>`. The example arguments are as follows:
* 1 - `DeviceCodeFlowSample.go` without cancellation timeout
* 2 - `UsernamePasswordPublicFlowSample.go`
70 changes: 70 additions & 0 deletions examples/SampleUtils.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT license.

package main

import (
"encoding/json"
"io/ioutil"
"os"

msalgo "github.com/AzureAD/microsoft-authentication-library-for-go/src/msal"
log "github.com/sirupsen/logrus"
)

//Config represents the config.json required to run the samples
type Config struct {
ClientID string `json:"client_id"`
Authority string `json:"authority"`
Scopes []string `json:"scopes"`
Username string `json:"username"`
Password string `json:"password"`
}

//CreateConfig creates the Config struct from a json file
func CreateConfig(fileName string) *Config {
jsonFile, err := os.Open(fileName)
if err != nil {
log.Fatal(err)
}
defer jsonFile.Close()
data, err := ioutil.ReadAll(jsonFile)
config := &Config{}
err = json.Unmarshal(data, config)
if err != nil {
log.Fatal(err)
}
return config
}

//GetClientID returns the Client ID of the config
func (c *Config) GetClientID() string {
return c.ClientID
}

//GetAuthority returns the authority URI of the config
func (c *Config) GetAuthority() string {
return c.Authority
}

//GetScopes returns all the scopes of the config
func (c *Config) GetScopes() []string {
return c.Scopes
}

//GetUsername returns the username of the config
func (c *Config) GetUsername() string {
return c.Username
}

//GetPassword returns the password of the config
func (c *Config) GetPassword() string {
return c.Password
}

//createPCAParams is used to instantiate the parameters to create the Public Client Application
func createPCAParams(clientID string, authority string) *msalgo.PublicClientApplicationParameters {
pcaParams := msalgo.CreatePublicClientApplicationParameters(clientID)
pcaParams.SetAadAuthority(authority)
return pcaParams
}
14 changes: 14 additions & 0 deletions examples/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package main

import (
"os"
)

func main() {
exampleType := os.Args[1]
if exampleType == "1" {
acquireTokenDeviceCode()
} else if exampleType == "2" {
acquireByUsernamePasswordPublic()
}
}
2 changes: 1 addition & 1 deletion getpackages.cmd
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Rem getpackages
Rem push ./src

go get -u github.com/sirupsen/logrus
go get -u github.com/shirou/gopsutil/host
go get -u github.com/shirou/gopsutil@v1
go get -u github.com/twinj/uuid
go get -u golang.org/x/crypto/ssh/terminal
go get -u github.com/AzureAD\microsoft-authentication-library-for-go/src/internal/msalbase
Expand Down
12 changes: 12 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
module github.com/AzureAD/microsoft-authentication-library-for-go

go 1.14

require (
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d // indirect
github.com/go-ole/go-ole v1.2.4 // indirect
github.com/shirou/gopsutil v2.20.5+incompatible
github.com/sirupsen/logrus v1.6.0
github.com/twinj/uuid v1.0.0
golang.org/x/sys v0.0.0-20200610111108-226ff32320da // indirect
)
19 changes: 19 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-ole/go-ole v1.2.4 h1:nNBDSCOigTSiarFpYE9J/KtEA1IOW4CNeqT9TQDqCxI=
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/shirou/gopsutil v2.20.5+incompatible h1:tYH07UPoQt0OCQdgWWMgYHy3/a9bcxNpBIysykNIP7I=
github.com/shirou/gopsutil v2.20.5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/twinj/uuid v1.0.0 h1:fzz7COZnDrXGTAOHGuUGYd6sG+JMq+AoE7+Jlu0przk=
github.com/twinj/uuid v1.0.0/go.mod h1:mMgcE1RHFUFqe5AfiwlINXisXfDGro23fWdPUfOMjRY=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200610111108-226ff32320da h1:bGb80FudwxpeucJUjPYJXuJ8Hk91vNtfvrymzwiei38=
golang.org/x/sys v0.0.0-20200610111108-226ff32320da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
24 changes: 0 additions & 24 deletions src/AcquireTokenDeviceCodeParameters.go

This file was deleted.

91 changes: 0 additions & 91 deletions src/examples/msalconsole/main.go

This file was deleted.

14 changes: 12 additions & 2 deletions src/internal/msalbase/DeviceCodeResult.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"time"
)

//DeviceCodeResult stores the response from the STS device code endpoint
type DeviceCodeResult struct {
userCode string
deviceCode string
Expand All @@ -19,43 +20,52 @@ type DeviceCodeResult struct {
scopes []string
}

//CreateDeviceCodeResult creates a DeviceCodeResult instance
func CreateDeviceCodeResult(userCode string, deviceCode string, verificationURL string, expiresOn time.Time, interval int, message string, clientID string, scopes []string) *DeviceCodeResult {
return &DeviceCodeResult{userCode, deviceCode, verificationURL, expiresOn, interval, message, clientID, scopes}
}

func (r DeviceCodeResult) String() string {
return fmt.Sprintf("UserCode: (%v)\nDeviceCode: (%v)\nURL: (%v)\nMessage: (%v)\n", r.GetUserCode(), r.GetDeviceCode(), r.GetVerificationURL(), r.GetMessage())
func (dcr DeviceCodeResult) String() string {
return fmt.Sprintf("UserCode: (%v)\nDeviceCode: (%v)\nURL: (%v)\nMessage: (%v)\n", dcr.GetUserCode(), dcr.GetDeviceCode(), dcr.GetVerificationURL(), dcr.GetMessage())

}

//GetUserCode returns the code the user needs to provide when authentication at the verification URI
func (dcr *DeviceCodeResult) GetUserCode() string {
return dcr.userCode
}

//GetDeviceCode returns the code used in the access token request
func (dcr *DeviceCodeResult) GetDeviceCode() string {
return dcr.deviceCode
}

//GetVerificationURL returns the URL where user can authenticate
func (dcr *DeviceCodeResult) GetVerificationURL() string {
return dcr.verificationURL
}

//GetExpiresOn returns the expiration time of device code in seconds
func (dcr *DeviceCodeResult) GetExpiresOn() time.Time {
return dcr.expiresOn
}

//GetInterval returns the interval at which the STS should be polled at
func (dcr *DeviceCodeResult) GetInterval() int {
return dcr.interval
}

//GetMessage returns the message which should be displayed to the user
func (dcr *DeviceCodeResult) GetMessage() string {
return dcr.message
}

//GetClientID returns the UUID issued by the authorization server for your application
func (dcr *DeviceCodeResult) GetClientID() string {
return dcr.clientID
}

//GetScopes returns the scopes used to request access a protected API
func (dcr *DeviceCodeResult) GetScopes() []string {
return dcr.scopes
}
4 changes: 4 additions & 0 deletions src/internal/msalbase/TokenResponse.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ func (tr *TokenResponse) IsAuthorizationPending() bool {
return tr.baseResponse.Error == "authorization_pending"
}

func (tr *TokenResponse) IsSlowDown() bool {
return tr.baseResponse.Error == "slow_down"
}

func (tr *TokenResponse) GetAccessToken() string {
return tr.accessToken
}
Expand Down
2 changes: 1 addition & 1 deletion src/internal/requests/AadInstanceDiscovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ package requests
import (
"sync"

"internal/msalbase"
"github.com/AzureAD/microsoft-authentication-library-for-go/src/internal/msalbase"
)

var instanceDiscoveryCache = map[string]*instanceDiscoveryMetadata{}
Expand Down
Loading

0 comments on commit ee1f38a

Please sign in to comment.