|
@@ -16,14 +16,80 @@ type Client struct {
|
|
tenantID string
|
|
tenantID string
|
|
}
|
|
}
|
|
|
|
|
|
-func NewAzureEntraIDClient() *Client {
|
|
|
|
|
|
+func NewAzureEntraIDClient(clientID, clientSecret, tenantID string) *Client {
|
|
|
|
+ return &Client{
|
|
|
|
+ clientID: clientID,
|
|
|
|
+ clientSecret: clientSecret,
|
|
|
|
+ tenantID: tenantID,
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func NewAzureEntraIDClientFromSettings() *Client {
|
|
settings := logic.GetServerSettings()
|
|
settings := logic.GetServerSettings()
|
|
|
|
|
|
- return &Client{
|
|
|
|
- clientID: settings.ClientID,
|
|
|
|
- clientSecret: settings.ClientSecret,
|
|
|
|
- tenantID: settings.AzureTenant,
|
|
|
|
|
|
+ return NewAzureEntraIDClient(settings.ClientID, settings.ClientSecret, settings.AzureTenant)
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (a *Client) Verify() error {
|
|
|
|
+ accessToken, err := a.getAccessToken()
|
|
|
|
+ if err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ client := &http.Client{}
|
|
|
|
+ req, err := http.NewRequest("GET", "https://graph.microsoft.com/v1.0/users?$select=id,userPrincipalName,displayName,accountEnabled&$top=1", nil)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ req.Header.Add("Authorization", "Bearer "+accessToken)
|
|
|
|
+ req.Header.Add("Accept", "application/json")
|
|
|
|
+
|
|
|
|
+ resp, err := client.Do(req)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ defer func() {
|
|
|
|
+ _ = resp.Body.Close()
|
|
|
|
+ }()
|
|
|
|
+
|
|
|
|
+ var users getUsersResponse
|
|
|
|
+ err = json.NewDecoder(resp.Body).Decode(&users)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return err
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+ if users.Error.Code != "" {
|
|
|
|
+ return errors.New(users.Error.Message)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ req, err = http.NewRequest("GET", "https://graph.microsoft.com/v1.0/groups?$select=id,displayName&$expand=members($select=id)&$top=1", nil)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ req.Header.Add("Authorization", "Bearer "+accessToken)
|
|
|
|
+ req.Header.Add("Accept", "application/json")
|
|
|
|
+
|
|
|
|
+ resp, err = client.Do(req)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+ defer func() {
|
|
|
|
+ _ = resp.Body.Close()
|
|
|
|
+ }()
|
|
|
|
+
|
|
|
|
+ var groups getGroupsResponse
|
|
|
|
+ err = json.NewDecoder(resp.Body).Decode(&groups)
|
|
|
|
+ if err != nil {
|
|
|
|
+ return err
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ if groups.Error.Code != "" {
|
|
|
|
+ return errors.New(groups.Error.Message)
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ return nil
|
|
}
|
|
}
|
|
|
|
|
|
func (a *Client) GetUsers() ([]idp.User, error) {
|
|
func (a *Client) GetUsers() ([]idp.User, error) {
|
|
@@ -55,6 +121,10 @@ func (a *Client) GetUsers() ([]idp.User, error) {
|
|
return nil, err
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if users.Error.Code != "" {
|
|
|
|
+ return nil, errors.New(users.Error.Message)
|
|
|
|
+ }
|
|
|
|
+
|
|
retval := make([]idp.User, len(users.Value))
|
|
retval := make([]idp.User, len(users.Value))
|
|
for i, user := range users.Value {
|
|
for i, user := range users.Value {
|
|
retval[i] = idp.User{
|
|
retval[i] = idp.User{
|
|
@@ -97,6 +167,10 @@ func (a *Client) GetGroups() ([]idp.Group, error) {
|
|
return nil, err
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+ if groups.Error.Code != "" {
|
|
|
|
+ return nil, errors.New(groups.Error.Message)
|
|
|
|
+ }
|
|
|
|
+
|
|
retval := make([]idp.Group, len(groups.Value))
|
|
retval := make([]idp.Group, len(groups.Value))
|
|
for i, group := range groups.Value {
|
|
for i, group := range groups.Value {
|
|
retvalMembers := make([]string, len(group.Members))
|
|
retvalMembers := make([]string, len(group.Members))
|
|
@@ -141,11 +215,12 @@ func (a *Client) getAccessToken() (string, error) {
|
|
return token, nil
|
|
return token, nil
|
|
}
|
|
}
|
|
|
|
|
|
- return "", errors.New("failed to get access token")
|
|
|
|
|
|
+ return "", errors.New("invalid credentials")
|
|
}
|
|
}
|
|
|
|
|
|
type getUsersResponse struct {
|
|
type getUsersResponse struct {
|
|
- OdataContext string `json:"@odata.context"`
|
|
|
|
|
|
+ Error errorResponse `json:"error"`
|
|
|
|
+ OdataContext string `json:"@odata.context"`
|
|
Value []struct {
|
|
Value []struct {
|
|
Id string `json:"id"`
|
|
Id string `json:"id"`
|
|
UserPrincipalName string `json:"userPrincipalName"`
|
|
UserPrincipalName string `json:"userPrincipalName"`
|
|
@@ -155,7 +230,8 @@ type getUsersResponse struct {
|
|
}
|
|
}
|
|
|
|
|
|
type getGroupsResponse struct {
|
|
type getGroupsResponse struct {
|
|
- OdataContext string `json:"@odata.context"`
|
|
|
|
|
|
+ Error errorResponse `json:"error"`
|
|
|
|
+ OdataContext string `json:"@odata.context"`
|
|
Value []struct {
|
|
Value []struct {
|
|
Id string `json:"id"`
|
|
Id string `json:"id"`
|
|
DisplayName string `json:"displayName"`
|
|
DisplayName string `json:"displayName"`
|
|
@@ -165,3 +241,13 @@ type getGroupsResponse struct {
|
|
} `json:"members"`
|
|
} `json:"members"`
|
|
} `json:"value"`
|
|
} `json:"value"`
|
|
}
|
|
}
|
|
|
|
+
|
|
|
|
+type errorResponse struct {
|
|
|
|
+ Code string `json:"code"`
|
|
|
|
+ Message string `json:"message"`
|
|
|
|
+ InnerError struct {
|
|
|
|
+ Date string `json:"date"`
|
|
|
|
+ RequestId string `json:"request-id"`
|
|
|
|
+ ClientRequestId string `json:"client-request-id"`
|
|
|
|
+ } `json:"innerError"`
|
|
|
|
+}
|