locked
Spring Boot (v2.1.6) Microsoft Planner Integration RRS feed

  • Question

  • I am working on a Spring Boot service that integrates the web API for Microsoft Planner. I've created an app registration in Azure and granted the permissions for Groups.Read.All and Users.Read.All (delegated).

    What I am currently attempting to implement is server side oauth authentication. As of now, the `authorization-grant-type` that I am using is `client_credentials`. With the below WebSecurityConfiguration I am able to make a request to endpoint that I created called `/test`. The endpoint is a `GET` request that has an argument `@RegisteredOAuth2AuthorizedClient("azure") OAuth2AuthorizedClient authorizedClient`.

    ```java
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
    import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
    import org.springframework.security.oauth2.client.oidc.userinfo.OidcUserRequest;
    import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
    import org.springframework.security.oauth2.core.oidc.user.OidcUser;

    @EnableWebSecurity
    public class WebSecurityConfiguration {

        @Configuration
        public class AzureSecurityConfiguration extends WebSecurityConfigurerAdapter {

            private OAuth2UserService<OidcUserRequest, OidcUser> oAuth2UserService;

            @Autowired
            public AzureSecurityConfiguration(OAuth2UserService<OidcUserRequest, OidcUser> oAuth2UserService) {
                this.oAuth2UserService = oAuth2UserService;
            }

            @Override
            protected void configure(HttpSecurity http) throws Exception {
                http.authorizeRequests().anyRequest().permitAll().and()
                    .csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()).and()
                        .addFilterBefore(authenticationFilter, UsernamePasswordAuthenticationFilter.class);
            }
        }
    }
    ```

    With that, when the request is made Spring will make the necessary request to Microsofts OAuth endpoints to get an access token.

    When using this token to make a request (w/Postman) to a Microsoft Planner API endpoint, `https://graph.microsoft.com/v1.0/users/{username}/planner/tasks` I get the following response:

    ```json
    {
        "error": {
            "code": "UnknownError",
            "message": "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\r\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n<head>\r\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\"/>\r\n<title>401 - Unauthorized: Access is denied due to invalid credentials.</title>\r\n<style type=\"text/css\">\r\n<!--\r\nbody{margin:0;font-size:.7em;font-family:Verdana, Arial, Helvetica, sans-serif;background:#EEEEEE;}\r\nfieldset{padding:0 15px 10px 15px;} \r\nh1{font-size:2.4em;margin:0;color:#FFF;}\r\nh2{font-size:1.7em;margin:0;color:#CC0000;} \r\nh3{font-size:1.2em;margin:10px 0 0 0;color:#000000;} \r\n#header{width:96%;margin:0 0 0 0;padding:6px 2% 6px 2%;font-family:\"trebuchet MS\", Verdana, sans-serif;color:#FFF;\r\nbackground-color:#555555;}\r\n#content{margin:0 0 0 2%;;}\r\n.content-container{background:#FFF;width:96%;margin-top:8px;padding:10px;;}\r\n-->\r\n</style>\r\n</head>\r\n<body>\r\n<div id=\"header\"><h1>Server Error</h1></div>\r\n<div id=\"content\">\r\n <div class=\"content-container\"><fieldset>\r\n  <h2>401 - Unauthorized: Access is denied due to invalid credentials.</h2>\r\n  <h3>You do not have permission to view this directory or page using the credentials that you supplied.</h3>\r\n </fieldset></div>\r\n</div>\r\n</body>\r\n</html>\r\n",
            "innerError": {
                "request-id": "some randomly generated id",
                "date": "time stamp of request"
            }
        }
    }
    ```


    The scope defined that gets me this far is `https://graph.microsoft.com/.default`. At this point I'm sure why this works but when defining the scope as `https://graph.microsoft.com/users.read.all` or `https://graph.microsoft.com/users.read.all` does not work, and gets me an error stating that the provided value for the input parameter is not valid.

    Groups.Read.All and Users.Read.All are the API permissions that I have granted to the app registration in Azure so I am not sure why that fails.

    My ultimate goal is project is to leverage Microsoft's Graph API to create, delete, update MS Planner Tasks for a given user. I would like the service to log the user in instead of the user having to manually log into Office 360. It would be nice to make it seamless to the user.

    Any help would be most appreciated.

    SIDE NOTE: I've already looked through the azure github at the samples they provide and they were helpful to a certain extent.
    Monday, July 22, 2019 7:11 PM

Answers

All replies

  • Might try asking for help over here.

    https://techcommunity.microsoft.com/t5/Planner/ct-p/Planner

    https://stackoverflow.com/questions/tagged/microsoft-graph

     

     



    Regards, Dave Patrick ....
    Microsoft Certified Professional
    Microsoft MVP [Windows Server] Datacenter Management

    Disclaimer: This posting is provided "AS IS" with no warranties or guarantees, and confers no rights.


    Monday, July 22, 2019 9:08 PM
  • Stack Overflow thread:

    https://stackoverflow.com/questions/57047044/spring-boot-v2-1-6-microsoft-planner-integration

    While this is outside of my area of expertise (Application Insights), the following answer may be related to the "You do not have permission to view this directory" error you are encountering:

    https://stackoverflow.com/questions/44337449/postman-you-do-not-have-permission-to-view-this-directory-or-page-with-bearer


    "There are two concepts client and resource server in the OAuth 2.0 Authorization Framework(refer rfc6749). When the client calls the resource server, the resource server will verify the token passed in the request. For example, it will verify the signature, issuer, client id, audience etc.

    client: An application making protected resource requests on behalf of the resource owner and with its authorization. The term "client" does not imply any particular implementation characteristics (e.g., whether the application executes on a server, a desktop, or other devices).

    resource server: The server hosting the protected resources, capable of accepting and responding to protected resource requests using access tokens.

    In your scenario, you were acquire the access_token for the Azure AD Graph(https://graph.windows.net). However, the audience you config at the portal doesn't match the aud claim in the access_token. To fix the issue, we can use the app registered at Azure AD as both client and resource. If that, we need to acquire the access token using the Application IDinstead of App ID URI. And config this value as the ALLOWED TOKEN AUDIENCES on the Azure portal.

    Or we can just to register two apps in Azure AD to represent the client app and resource app separately. And using the client app to acquire the token for the resource app. If this, the value of resource should the App ID URI of resource app and we also need to config it as the ALLOWED TOKEN AUDIENCES on the Azure portal."

    Monday, July 22, 2019 9:09 PM
  • I've tried stackoverflow, seems like no one has run into this issue. Starting to think this isn't possible. I'll try the techcommunity and see what happens. Thank you for your response.
    Tuesday, July 23, 2019 12:55 PM
  • Sounds good, you're welcome.

     

     



    Regards, Dave Patrick ....
    Microsoft Certified Professional
    Microsoft MVP [Windows Server] Datacenter Management

    Disclaimer: This posting is provided "AS IS" with no warranties or guarantees, and confers no rights.

    Tuesday, July 23, 2019 12:57 PM
  • @kobulloc-MSFT

    Thanks for responding! I'm not exactly how audiences work or how they are configured in the Azure Portal. What steps do I need to take to configure the app registered in Azure as both the client and resource? When using https://jwt.ms to inspect the token, the audience is set to "aud": "https://graph.microsoft.com".


    Tuesday, July 23, 2019 1:14 PM
  • This is "where is" forum for direction on where best to ask questions so I'd ask in forums I linked or another option is you can start a case here with microsoft product support.

    https://support.microsoft.com/en-us/hub/4343728/support-for-business

     

     



    Regards, Dave Patrick ....
    Microsoft Certified Professional
    Microsoft MVP [Windows Server] Datacenter Management

    Disclaimer: This posting is provided "AS IS" with no warranties or guarantees, and confers no rights.

    Tuesday, July 23, 2019 1:28 PM