-
-
Notifications
You must be signed in to change notification settings - Fork 1.9k
feat: support MS Entra ID app role authorization #3110
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
feat: support MS Entra ID app role authorization #3110
Conversation
ad85975 to
e54d18d
Compare
providers/keycloak_oidc.go
Outdated
| payload, err := extractAccessTokenPayload(s) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("malformed access token, couldn't extract jwt payload: %v", err) | ||
| return nil, err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please wrap error messages
| return nil, err | |
| return nil, fmt.Errorf("couldn't extract access token payload: %w", err) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tuunit done.
providers/ms_entra_id.go
Outdated
| return err | ||
| } | ||
|
|
||
| var claim rolesClaim | ||
| if err := json.Unmarshal(payload, &claim); err != nil { | ||
| return err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please wrap all returned errors. Otherwise tracing things gets messy really quickly
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please wrap all returned errors. Otherwise tracing things gets messy really quickly
@tuunit Done.
providers/util.go
Outdated
| parts := strings.Split(s.AccessToken, ".") | ||
| if len(parts) < 2 { | ||
| return nil, fmt.Errorf("malformed access token, expected 3 parts got %d", len(parts)) | ||
| } | ||
|
|
||
| payload, err := base64.RawURLEncoding.DecodeString(parts[1]) | ||
| if err != nil { | ||
| return nil, fmt.Errorf("malformed access token, couldn't extract jwt payload: %v", err) | ||
| } | ||
|
|
||
| return payload, err |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you we use the claimExtractor provided in provider_data.go->getClaimExtractor()?
Do you need the roles claim from the AccessToken instead of the roles claim in the IdToken?
What exactly is the difference here?
https://learn.microsoft.com/en-us/entra/identity-platform/id-token-claims-reference
https://learn.microsoft.com/en-us/entra/identity-platform/access-token-claims-reference
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@xiaobao520123 thanks for contributing. I'm not an Entra user so my experience with it is limited to some testing environments. Could you clarify the differences?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@xiaobao520123 thanks for contributing. I'm not an Entra user so my experience with it is limited to some testing environments. Could you clarify the differences?
@tuunit ID token and Access Token are two different concepts in MS Entra system. ID token tells the client/server who the user is, mainly for authentication with basic profile information of the user in it. Access Token tells the server what the user can access within a certain range of cloud resources or applications, and it is more about doing authorization.
In our case, we register a group of users on one single Enterprise Application with a custom role assigned onto the group. After the client calls MS Identity Platform for an Access Token of that application, the payload within the token allows the server to check if the user has the permission to access that Application. Precisely, by the roles claim. Often Access Tokens are related to one or a small range of cloud resource, while ID token is more like a global info in the whole system.
I think provider_data.go->getClaimExtractor() is designed for ID tokens, so I prefer to add a new function to extract the payload of Access Token.
|
@xiaobao520123 please add a changelog entry as well :) |
|
|
||
| // Role enables to restrict login to users with app role | ||
| Roles []string `json:"roles,omitempty"` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Run make generate to update the alpha docs
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@tuunit Done.
aa6b1a8 to
601e505
Compare
601e505 to
f5a32a3
Compare
Description
Using configuration '--allowed-role' to support Microsoft Entra ID app role authorization.
Motivation and Context
Hi, I'm from Microsoft.
My daily workload typically involves doing authorization via Azure RBAC.
Due to our Azure tenant policy settings, neither Microsoft.GraphAPI nor 'groups' is available for user authentication by oauth2-proxy. Setting app role registration to users and then implementing authorization by looking at the 'roles' claim of each access token is the only one possible solution. After looking through oauth2-proxy implementation, I added authorization by app roles to provider ms-entra-id, which was built on top of current '--allowed-role' setting.
To test this feature, I created my own Application in my Azure Cloud. And it was able to see and check user's roles available in every JWT token, then made sure the user had one of authorized roles.
Authorization through app role is part of Azure RBAC ecosystem. You can learn more about app role here: Add app roles to your application and receive them in the token
How Has This Been Tested?
Checklist: