sonar-auth-aad icon indicating copy to clipboard operation
sonar-auth-aad copied to clipboard

Support for Microsoft Graph for login instead of AAD Graph

Open ghjimmy opened this issue 4 years ago • 5 comments

According to Microsoft, there is no addition support being added for AAD Graph and has not been since July 2020:

Starting June 30th, 2020 we will no longer add any new features to Azure AD Graph API. We strongly recommend that you use Microsoft Graph API instead of Azure AD Graph API to access Azure Active Directory resources.

which then links to https://techcommunity.microsoft.com/t5/azure-active-directory-identity/update-your-applications-to-use-microsoft-authentication-library/ba-p/1257363

Are there any plans to update the plugin to use Microsoft Graph API?

ghjimmy avatar Sep 07 '21 12:09 ghjimmy

I'm currently working on some updates to the plugin that will drop the deprecated ADAL4J library and move to a more generic OAuth library, as MSAL4J is overkill for this project. With that move, there will also be a move to the MS Graph API. Unfortunately, this also necessitates a larger refactor, and I'm basing the new structure on the GH and similar OAuth-style plugins to allow better testing instead of having all the logic in the callback.

That said, Microsoft is not removing the older AAD Graph API, they just aren't adding anything new to it. As we're only using existing functionality, I don't expect any problems continuing with the old system until I can land my private work once it's in a semi-usable state.

srvrguy avatar Sep 22 '21 17:09 srvrguy

Any update on this?

I'm getting complaints from tenant owner about ADAL usage. https://docs.microsoft.com/en-us/azure/active-directory/develop/msal-migration

If you choose not to migrate to MSAL before ADAL support ends in December, 2022, you put your app's security at risk. Existing apps that use ADAL will continue to work after the end-of-support date, but Microsoft will no longer release security fixes on ADAL.

kimsandbergsolita avatar Aug 03 '22 09:08 kimsandbergsolita

It's in the pipeline.

Since that post, the place I work has gone through a lot of changes and left me with little time to handle this plugin. Since the plugin continues to work, it's been a bit lower priority. I still have my earlier work and hopefully will have some time coming up where I can concentrate on finishing that work and getting it landed.

I did publish a new version yesterday with some changes that had been contributed earlier and other cleanup I had been doing in preparation for swapping out ADAL4J.

srvrguy avatar Aug 03 '22 16:08 srvrguy

@srvrguy Any update on when these changes are going to be available considering ADAL support is going to end in December 2022?

sudeep1607 avatar Oct 20 '22 09:10 sudeep1607

I don't have a timeline currently. Work is progressing, and mainly I have to finish group sync support and compatibility (with the user data ADAL4J provides). That's the short of it. A longer explanation follows:

First, on the code. I know that MSAL4J is marked as the successor to the ADAL4J project. The thing is that MSAL4J is extreme overkill for what this plugin does, which is just allowing SSO. MSAL4J is very much positioned to be part of code where you're doing a lot more than just that, and the complexity shows. Since there is a migration path for our use, I did attempt to use this. Unfortunately, it kept resulting in strange errors. I couldn't determine if it was something I was doing or just how SonarQube works. Eventually, I settled on just implementing the SSO manually using the Nimbus OAuth SDK. This has gone a lot smoother and allowed me to also add in some extra security like checking the tokens to match the audience ID and that the returned data is what we should expect. Unfortunately, I also have to implement functionality that ADAL4J was providing, like parsing out the user info from the tokens we get. To keep compatible with existing installs, I also have to ensure that it's basically doing it the exact same way. Likewise, once I get the user portion settled, I have to review the group sync functionality and ensure it's still working. That part is handled outside ADAL4J, so I hope that it will be a matter of simply uncommenting the code.

Second, on my time for this project. I started contributing to this project when the company where I was working started to implement Sonarqube scanning on the main product it offered to clients. Group support was one of the major draws along with the fact that I didn't have to manage a whole separate account structure. Since the time I began contributing, the company where I work has changed twice, both as a result of an acquisition. The first time wasn't very disruptive as the acquiring company mainly wanted the product to launch their own services. With the second acquisition, a much larger company acquired the combined company and I've been slowly integrated into the much larger DevOps group at this place. It's resulted in a large loss of time for projects like this as I learn and train on the way this company handles things. I'm glad that I can still work on this project with their knowledge, but work on the stuff that keeps them in business takes priority (and rightly so) over volunteer work.

I really hope to be able to get the ADAL4J removal complete before the discontinuation of that project, but this plugin will continue to work even after that date. It is just that, as time passes, it will require more understanding of what possible security issues continuing to use that component will bring up.

srvrguy avatar Oct 21 '22 16:10 srvrguy

Update on progress:

Group sync using the default group sync method (using the access token from the user) is working from my limited tests. I haven't implemented the newer client credential method yet. The retrieval is using the MS Graph Java SDK, so the plugin doesn't need all the custom JSON parsing and pagination code any longer.

Once group sync is complete, I'll post the work publicly on the develop branch for anyone that wants to review and suggest changes. All that will be left are compatibility tests and updating/creating unit tests for the new code.

srvrguy avatar Oct 26 '22 20:10 srvrguy

Hello, any news on this issue? Has it been fixed in the latest release (1.3.2)? Thanks in advance!

vittoriocanilli avatar Nov 14 '22 16:11 vittoriocanilli

1.3.2 is only a patch release that updated commons-text to resolve a CVE. The changes for dropping ADAL4J and moving to MS Graph is large enough that it will be designated as version 2 when it's released. I don't have the work in this repo right now, but probably will soon as an update on the develop branch. You can take a look at the "feature/oauth-rewrite" branch over at the srvrguy/sonar-auth-aad fork to see my in-progress work. Once it's merged here I'd be happy to accept any improvements, especially in increasing unit testing.

srvrguy avatar Nov 14 '22 19:11 srvrguy

Thank you so much for the information 👍 I look forward to version 2

vittoriocanilli avatar Nov 15 '22 09:11 vittoriocanilli

Updated code is now in the develop branch. I'd appreciate users testing this code in their installs, if they can. I've done some preliminary tests against two different setups, but I know there's a lot of variation in setups out there. If you can't compile, you can download a binary from the action artifact. Just go to the Test and Package action and select the newest run in the "develop" branch.

srvrguy avatar Nov 17 '22 20:11 srvrguy

I have downloaded the plugin binary from your Actions pipeline and I have installed it in my SonarQube instance, but I get this error when I try to authenticate:

You're not authorized to access this page. Please contact the administrator.

Reason: class com.microsoft.graph.models.DirectoryRole cannot be cast to class com.microsoft.graph.models.Group (com.microsoft.graph.models.DirectoryRole and com.microsoft.graph.models.Group are in unnamed module of loader org.sonar.classloader.ClassRealm @26865482)

Do I have to add any other API permission to my Azure app registrations? Before using this beta version of the plugin, the plugin worked only with this API permission:

  • https://graph.microsoft.com/Directory.AccessAsUser.All

After the first login using the beta version, the login screen has let me add these API permissions:

  • https://graph.microsoft.com/email
  • https://graph.microsoft.com/openid
  • https://graph.microsoft.com/profile
  • https://graph.microsoft.com/User.Read

vittoriocanilli avatar Nov 23 '22 14:11 vittoriocanilli

That is odd. In my tests, I've only needed to allow two permissions for MS Graph: User.Read (needed for basic login) and Directory.Read.All (for group sync). Both permissions are delegated type for the traditional flow. This is on an application I created (via the portal) only three weeks ago for testing to make sure that the setup process wasn't vastly different for new registrations. I do have the ID tokens enabled under the authentication settings, but I also have a test app with no permissions that works okay for basic sign-in and doesn't have that option enabled.

My test AAD is on the Free tier and doesn't have any customizations made to it.

Does the web.log show anything interesting in it? I've added a bunch more logging so when things fail it might provide more help in troubleshooting. If you post lines, please be sure to redact any sensitive info including any GUIDs (to be safe).

srvrguy avatar Nov 23 '22 19:11 srvrguy

Hey @srvrguy , We've tested the "develop" plug-in and it's working well for us. That said, 1 of our users also experienced the same error as @vittoriocanilli, so it might be worth investigating.

In the logs, I can see something about an invalid cookie just before the java error, but nothing else:

2022.11.23 00:44:55 INFO  web[AYSh7FcWMreCVXMYAAAM][o.a.t.u.h.p.Cookie] A cookie header was received [PS_DEVICEFEATURES=maf:0 width:1920 height:1080 clientWidth:1919 clientHeight:937 pixelratio:1 touch:0 geolocation:1 websockets:1 webworkers:1 datepicker:1 dtpicker:1 timepicker:1 dnd:1 sessionstorage:1 localstorage:1 history:1 canvas:1 svg:1 postmessage:1 hc:0;] that contained an invalid cookie. That cookie will be ignored.\n Note: further occurrences of this error will be logged at DEBUG level.
2022.11.23 00:46:37 ERROR web[AYSh7FcWMreCVXMYAABF][o.a.a.a.AadIdentityProvider] Exception:java.lang.ClassCastException: class com.microsoft.graph.models.DirectoryRole cannot be cast to class com.microsoft.graph.models.Group (com.microsoft.graph.models.DirectoryRole and com.microsoft.graph.models.Group are in unnamed module of loader org.sonar.classloader.ClassRealm @740dcae3)
2022.11.23 00:46:37 ERROR web[AYSh7FcWMreCVXMYAABF][o.a.a.a.AadIdentityProvider] Exception:org.sonar.api.server.authentication.UnauthorizedException: class com.microsoft.graph.models.DirectoryRole cannot be cast to class com.microsoft.graph.models.Group (com.microsoft.graph.models.DirectoryRole and com.microsoft.graph.models.Group are in unnamed module of loader org.sonar.classloader.ClassRealm @740dcae3)

Thanks!

extravio avatar Nov 23 '22 20:11 extravio

Okay. That's interesting. Can you give me some information on your setup and also that user? Perhaps there's something specific on that user's account that's causing this. For example, guest/invite accounts that are homed in a different directory do behave differently.

srvrguy avatar Nov 23 '22 21:11 srvrguy

I could not find any explanation why this error occurred for this user. He can now log in successfully. So I guess version 2 can be released :)

extravio avatar Nov 24 '22 20:11 extravio

That is odd. In my tests, I've only needed to allow two permissions for MS Graph: User.Read (needed for basic login) and Directory.Read.All (for group sync). Both permissions are delegated type for the traditional flow. This is on an application I created (via the portal) only three weeks ago for testing to make sure that the setup process wasn't vastly different for new registrations. I do have the ID tokens enabled under the authentication settings, but I also have a test app with no permissions that works okay for basic sign-in and doesn't have that option enabled.

My test AAD is on the Free tier and doesn't have any customizations made to it.

Does the web.log show anything interesting in it? I've added a bunch more logging so when things fail it might provide more help in troubleshooting. If you post lines, please be sure to redact any sensitive info including any GUIDs (to be safe).

Hello @srvrguy, here is what I can find in my logs when I try to log in:

2022.11.29 08:59:20 ERROR web[AYSkxRipJtoNEpdUAILX][o.a.a.a.AadIdentityProvider] Exception:java.lang.ClassCastException: class com.microsoft.graph.models.DirectoryRole cannot be cast to class com.microsoft.graph.models.Group (com.microsoft.graph.models.DirectoryRole and com.microsoft.graph.models.Group are in unnamed module of loader org.sonar.classloader.ClassRealm @26865482)
2022.11.29 08:59:20 ERROR web[AYSkxRipJtoNEpdUAILX][o.a.a.a.AadIdentityProvider] Exception:org.sonar.api.server.authentication.UnauthorizedException: class com.microsoft.graph.models.DirectoryRole cannot be cast to class com.microsoft.graph.models.Group (com.microsoft.graph.models.DirectoryRole and com.microsoft.graph.models.Group are in unnamed module of loader org.sonar.classloader.ClassRealm @26865482)

I can try to adjust the permissions of my Azure app registration to have it matching yours.

vittoriocanilli avatar Nov 29 '22 09:11 vittoriocanilli

@srvrguy I have just added the same permission in my Azure app registration as yours and I have removed the permissions that I had before, but I still get the same errors when I try to log in.

vittoriocanilli avatar Nov 29 '22 09:11 vittoriocanilli

That's odd. Something must be different, and I'd like to at least handle the issue a bit more sanely. It's obviously happening when communicating with MS Graph, but the problem is finding out the cause.

@vittoriocanilli, if you look at my code commits, you'll see an e-mail address. Can you contact me on that? I can provide a build with a bit more debugging/logging so I can at least try to track down the exact code area where it's failing.

srvrguy avatar Dec 02 '22 18:12 srvrguy

I found the issue and there's a new automated build over at the GH action. If you were having that issue, please try the new snapshot.

srvrguy avatar Dec 06 '22 22:12 srvrguy

Hi @srvrguy, thanks for your messages and sorry for the late reply.

I have managed today to setup a new environment with the latest build that I got in the GH action pipeline of your last message and I can confirm that the authentication works now 😃

The authentication is now working even with the only API permission that I had in my Azure app registration originally:

  • https://graph.microsoft.com/Directory.AccessAsUser.All

vittoriocanilli avatar Dec 15 '22 13:12 vittoriocanilli

after trying the this snapshot I get an error that the email-address is already used by another user. so it looks like the user mapping fails and it want to create a new one. has there something changed here?

OneCyrus avatar Dec 22 '22 16:12 OneCyrus

Yes, the way the user information is created has changed due to differences between the v1 and v2 MS endpoints. I created a new issue, #144 for this issue. Please look there for updates on that problem.

srvrguy avatar Dec 24 '22 21:12 srvrguy

Given that the MS Graph and MS Auth v2 support is now part of the development code and we have working 2.0 snapshots, I'm going to close this issue as fixed. For problems with the 2.0 snapshots, please open a new issue for that specific problem and noting that it's a 2.0 issue.

srvrguy avatar Dec 24 '22 21:12 srvrguy