microsoft: option for group UUIDs instead of name and group whitelist

parent 20a858da
......@@ -88,6 +88,9 @@ a member of. `onlySecurityGroups` configuration option restricts the list to
include only security groups. By default all groups (security, Office 365,
mailing lists) are included.
By default, dex resolve groups ids to groups names, to keep groups ids, you can
specify the configuration option `groupNameFormat: id`.
It is possible to require a user to be a member of a particular group in order
to be successfully authenticated in dex. For example, with the following
configuration file only the users who are members of at least one of the listed
......@@ -110,3 +113,6 @@ connectors:
- developers
- devops
```
Also, `useGroupsAsWhitelist` configuration option, can restrict the groups
claims to include only the user's groups that are in the configured `groups`.
\ No newline at end of file
......@@ -19,12 +19,23 @@ import (
"github.com/dexidp/dex/pkg/log"
)
// GroupNameFormat represents the format of the group identifier
// we use type of string instead of int because it's easier to
// marshall/unmarshall
type GroupNameFormat string
// Possible values for GroupNameFormat
const (
GroupID GroupNameFormat = "id"
GroupName GroupNameFormat = "name"
)
const (
apiURL = "https://graph.microsoft.com"
// Microsoft requires this scope to access user's profile
scopeUser = "user.read"
// Microsoft requires this scope to list groups the user is a member of
// and resolve their UUIDs to groups names.
// and resolve their ids to groups names.
scopeGroups = "directory.read.all"
)
......@@ -36,6 +47,8 @@ type Config struct {
Tenant string `json:"tenant"`
OnlySecurityGroups bool `json:"onlySecurityGroups"`
Groups []string `json:"groups"`
GroupNameFormat GroupNameFormat `json:"groupNameFormat"`
UseGroupsAsWhitelist bool `json:"useGroupsAsWhitelist"`
}
// Open returns a strategy for logging in through Microsoft.
......@@ -47,6 +60,8 @@ func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error)
tenant: c.Tenant,
onlySecurityGroups: c.OnlySecurityGroups,
groups: c.Groups,
groupNameFormat: c.GroupNameFormat,
useGroupsAsWhitelist: c.UseGroupsAsWhitelist,
logger: logger,
}
// By default allow logins from both personal and business/school
......@@ -55,6 +70,15 @@ func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error)
m.tenant = "common"
}
// By default, use group names
switch m.groupNameFormat {
case "":
m.groupNameFormat = GroupName
case GroupID, GroupName:
default:
return nil, fmt.Errorf("invalid groupNameFormat: %s", m.groupNameFormat)
}
return &m, nil
}
......@@ -75,7 +99,9 @@ type microsoftConnector struct {
clientSecret string
tenant string
onlySecurityGroups bool
groupNameFormat GroupNameFormat
groups []string
useGroupsAsWhitelist bool
logger log.Logger
}
......@@ -300,24 +326,28 @@ type group struct {
Name string `json:"displayName"`
}
func (c *microsoftConnector) getGroups(ctx context.Context, client *http.Client, userID string) (groups []string, err error) {
ids, err := c.getGroupIDs(ctx, client)
func (c *microsoftConnector) getGroups(ctx context.Context, client *http.Client, userID string) ([]string, error) {
userGroups, err := c.getGroupIDs(ctx, client)
if err != nil {
return groups, err
return nil, err
}
groups, err = c.getGroupNames(ctx, client, ids)
if c.groupNameFormat == GroupName {
userGroups, err = c.getGroupNames(ctx, client, userGroups)
if err != nil {
return
return nil, err
}
}
// ensure that the user is in at least one required group
filteredGroups := groups_pkg.Filter(groups, c.groups)
filteredGroups := groups_pkg.Filter(userGroups, c.groups)
if len(c.groups) > 0 && len(filteredGroups) == 0 {
return nil, fmt.Errorf("microsoft: user %v not in any of the required groups", userID)
} else if c.useGroupsAsWhitelist {
return filteredGroups, nil
}
return
return userGroups, nil
}
func (c *microsoftConnector) getGroupIDs(ctx context.Context, client *http.Client) (ids []string, err error) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment