This is a standalone package for authenticating with Azure Active Directory from other Go libraries and applications, in particular the Azure SDK for Go.
Note: Despite the package's name it is not related to other "ADAL" libraries maintained in the github.com/AzureAD org. Issues should be opened in this repo's or the SDK's issue trackers.
go get -u github.com/Azure/go-autorest/autorest/adal
An Active Directory application is required in order to use this library. An application can be registered in the Azure Portal by following these guidelines or using the Azure CLI.
secret
credentialaz ad app create \
--display-name example-app \
--homepage https://example-app/home \
--identifier-uris https://example-app/app \
--password secret
Application ID
from previous stepaz ad sp create --id "Application ID"
Application ID
with appId
from step 1.openssl genrsa -out "example-app.key" 2048
openssl req -new -key "example-app.key" -subj "/CN=example-app" -out "example-app.csr"
openssl x509 -req -in "example-app.csr" -signkey "example-app.key" -out "example-app.crt" -days 10000
``` openssl pkcs12 -export -out "example-app.pfx" -inkey "example-app.key" -in "example-app.crt" -passout pass:
```
example-app.crt
``` certificateContents="$(tail -n+2 "example-app.crt" | head -n-1)"
az ad app create \ --display-name example-app \ --homepage https://example-app/home \ --identifier-uris https://example-app/app \ --key-usage Verify --end-date 2018-01-01 \ --key-value "${certificateContents}" ```
Application ID
from previous stepaz ad sp create --id "APPLICATION_ID"
APPLICATION_ID
with appId
from step 4.Azure relies on a Role-Based Access Control (RBAC) model to manage the access to resources at a fine-grained level. There is a set of pre-defined roles which can be assigned to a service principal of an Azure AD application depending of your needs.
az role assignment create --assigner "SERVICE_PRINCIPAL_ID" --role "ROLE_NAME"
SERVICE_PRINCIPAL_ID
with the appId
from previous step.ROLE_NAME
with a role name of your choice.It is also possible to define custom role definitions.
az role definition create --role-definition role-definition.json
role-definition.json
file.The common configuration used by all flows:
const activeDirectoryEndpoint = "https://login.microsoftonline.com/" tenantID := "TENANT_ID" oauthConfig, err := adal.NewOAuthConfig(activeDirectoryEndpoint, tenantID) applicationID := "APPLICATION_ID" callback := func(token adal.Token) error { // This is called after the token is acquired } // The resource for which the token is acquired resource := "https://management.core.windows.net/"
TENANT_ID
with your tenant ID.APPLICATION_ID
with the value from previous section.applicationSecret := "APPLICATION_SECRET" spt, err := adal.NewServicePrincipalToken( *oauthConfig, appliationID, applicationSecret, resource, callbacks...) if err != nil { return nil, err } // Acquire a new access token err = spt.Refresh() if (err == nil) { token := spt.Token }
APPLICATION_SECRET
with the password
value from previous section.certificatePath := "./example-app.pfx" certData, err := ioutil.ReadFile(certificatePath) if err != nil { return nil, fmt.Errorf("failed to read the certificate file (%s): %v", certificatePath, err) } // Get the certificate and private key from pfx file certificate, rsaPrivateKey, err := decodePkcs12(certData, "") if err != nil { return nil, fmt.Errorf("failed to decode pkcs12 certificate while creating spt: %v", err) } spt, err := adal.NewServicePrincipalTokenFromCertificate( *oauthConfig, applicationID, certificate, rsaPrivateKey, resource, callbacks...) // Acquire a new access token err = spt.Refresh() if (err == nil) { token := spt.Token }
oauthClient := &http.Client{} // Acquire the device code deviceCode, err := adal.InitiateDeviceAuth( oauthClient, *oauthConfig, applicationID, resource) if err != nil { return nil, fmt.Errorf("Failed to start device auth flow: %s", err) } // Display the authentication message fmt.Println(*deviceCode.Message) // Wait here until the user is authenticated token, err := adal.WaitForUserCompletion(oauthClient, deviceCode) if err != nil { return nil, fmt.Errorf("Failed to finish device auth flow: %s", err) } spt, err := adal.NewServicePrincipalTokenFromManualToken( *oauthConfig, applicationID, resource, *token, callbacks...) if (err == nil) { token := spt.Token }
spt, err := adal.NewServicePrincipalTokenFromUsernamePassword( *oauthConfig, applicationID, username, password, resource, callbacks...) if (err == nil) { token := spt.Token }
spt, err := adal.NewServicePrincipalTokenFromAuthorizationCode( *oauthConfig, applicationID, clientSecret, authorizationCode, redirectURI, resource, callbacks...) err = spt.Refresh() if (err == nil) { token := spt.Token }
A command line tool is available in cmd/adal.go
that can acquire a token for a given resource. It supports all flows mentioned above.
adal -h Usage of ./adal: -applicationId string application id -certificatePath string path to pk12/PFC application certificate -mode string authentication mode (device, secret, cert, refresh) (default "device") -resource string resource for which the token is requested -secret string application secret -tenantId string tenant id -tokenCachePath string location of oath token cache (default "/home/cgc/.adal/accessToken.json")
Example acquire a token for https://management.core.windows.net/
using device code flow:
adal -mode device \ -applicationId "APPLICATION_ID" \ -tenantId "TENANT_ID" \ -resource https://management.core.windows.net/