Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions sdk/boms/azure-spring-boot-bom/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.microsoft.azure</groupId>
<artifactId>azure-spring-boot-bom</artifactId>
<version>2.2.5-beta.1</version>
<packaging>pom</packaging>

<name>Azure Spring Boot BOM</name>
<description>BOM for Microsoft Azure Spring Boot Support</description>
<url>https://github.com/Azure/azure-sdk-for-java</url>

<licenses>
<license>
<name>The MIT License (MIT)</name>
<url>http://opensource.org/licenses/MIT</url>
<distribution>repo</distribution>
</license>
</licenses>

<developers>
<developer>
<id>microsoft</id>
<name>Microsoft Corporation</name>
</developer>
</developers>

<scm>
<connection>scm:git:git://github.com/azure/azure-sdk-for-java</connection>
<developerConnection>scm:git:git://github.com/azure/azure-sdk-for-java</developerConnection>
<url>https://github.com/azure/azure-sdk-for-java</url>
</scm>

<issueManagement>
<system>GitHub</system>
<url>https://github.com/azure/azure-sdk-for-java/issues</url>
</issueManagement>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>spring-data-cosmosdb</artifactId>
<version>2.2.3.FIX1</version> <!-- {x-version-update;com.microsoft.azure:spring-data-cosmosdb;external_dependency} -->
</dependency>
<dependency>
<groupId>com.microsoft.spring.data.gremlin</groupId>
<artifactId>spring-data-gremlin</artifactId>
<version>2.2.3</version> <!-- {x-version-update;com.microsoft.spring.data.gremlin:spring-data-gremlin;external_dependency} -->
</dependency>

<!-- Azure Dependencies Bom -->
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-spring-boot</artifactId>
<version>2.2.5-beta.1</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-spring-boot-starter</artifactId>
<version>2.2.5-beta.1</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-active-directory-spring-boot-starter</artifactId>
<version>2.2.5-beta.1</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-active-directory-b2c-spring-boot-starter</artifactId>
<version>2.2.5-beta.1</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-cosmosdb-spring-boot-starter</artifactId>
<version>2.2.5-beta.1</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-data-gremlin-spring-boot-starter</artifactId>
<version>2.2.5-beta.1</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-keyvault-secrets-spring-boot-starter</artifactId>
<version>2.2.5-beta.1</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-spring-boot-metrics-starter</artifactId>
<version>2.2.5-beta.1</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-servicebus-jms-spring-boot-starter</artifactId>
<version>2.2.5-beta.1</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
3 changes: 3 additions & 0 deletions sdk/boms/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,6 @@ stages:
- name: azure-sdk-bom
groupId: com.azure
safeName: azuresdkbom
- name: azure-spring-boot-bom
groupID: com.microsoft.azure
safeName: azurespringbootbom
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
# OAuth 2.0 Sample for Azure AD Spring Boot Starter client library for Java

## Key concepts
This sample illustrates how to use `azure-active-directory-spring-boot-starter` package to work with OAuth 2.0 and OpenID Connect protocols on Auzre. This sample will use Microsoft Graph API to retrieve user info. This is the key difference from [azure-spring-boot-sample-active-directory-backend](../azure-spring-boot-sample-active-directory-backend/README.md). It's reflected by these configurations in `appication.properties`:
```properties
azure.activedirectory.environment=global-v2-graph
azure.activedirectory.user-group.key=@odata.type
azure.activedirectory.user-group.value=#microsoft.graph.group
azure.activedirectory.user-group.object-id-key=id
```

## Getting started

### Register your application with your Azure Active Directory Tenant

Follow the guide [here](https://docs.microsoft.com/azure/active-directory/develop/quickstart-register-app).

### Configure groups for sign in user

In order to try the authorization action with this sample with minimum effort, [configure the user and groups in Azure Active Directory](https://docs.microsoft.com/azure/active-directory/active-directory-groups-create-azure-portal), configure the user with `group1`.


## Examples

### Configure application.properties

```properties
spring.security.oauth2.client.registration.azure.client-id=xxxxxx-your-client-id-xxxxxx
spring.security.oauth2.client.registration.azure.client-secret=xxxxxx-your-client-secret-xxxxxx

azure.activedirectory.tenant-id=xxxxxx-your-tenant-id-xxxxxx
# It's suggested the logged in user should at least belong to one of the below groups
# If not, the logged in user will not be able to access any authorization controller rest APIs
azure.activedirectory.active-directory-groups=group1, group2
```

### Run with Maven

```shell
# Under azure-spring-boot project root directory
mvn clean install -DskipTests
cd azure-spring-boot-samples
cd azure-spring-boot-sample-active-directory-backend-v2
mvn spring-boot:run
```

### Check the authentication and authorization

1. Access http://localhost:8080
2. Login
3. Access `group1 Message` link, should success
4. Access `group2 Message` link, should fail with forbidden error message


### <strong>*</strong> Take full control over every configuration property

If you want to adjust the configuration properties according to certain requirements, try below application.properties and change accordingly.

```properties
spring.security.oauth2.client.registration.azure.client-id=xxxxxx-your-client-id-xxxxxx
spring.security.oauth2.client.registration.azure.client-secret=xxxxxx-your-client-secret-xxxxxx
spring.security.oauth2.client.registration.azure.client-name=Azure
spring.security.oauth2.client.registration.azure.provider=azure-oauth-provider
spring.security.oauth2.client.registration.azure.scope=openid, https://graph.microsoft.com/user.read
spring.security.oauth2.client.registration.azure.redirect-uri-template={baseUrl}/login/oauth2/code/{registrationId}
spring.security.oauth2.client.registration.azure.client-authentication-method=basic
spring.security.oauth2.client.registration.azure.authorization-grant-type=authorization_code

spring.security.oauth2.client.provider.azure-oauth-provider.authorization-uri=https://login.microsoftonline.com/common/oauth2/authorize
spring.security.oauth2.client.provider.azure-oauth-provider.token-uri=https://login.microsoftonline.com/common/oauth2/token
spring.security.oauth2.client.provider.azure-oauth-provider.user-info-uri=https://login.microsoftonline.com/common/openid/userinfo
spring.security.oauth2.client.provider.azure-oauth-provider.jwk-set-uri=https://login.microsoftonline.com/common/discovery/keys
spring.security.oauth2.client.provider.azure-oauth-provider.user-name-attribute=name

azure.activedirectory.tenant-id=xxxxxx-your-tenant-id-xxxxxx
azure.activedirectory.active-directory-groups=group1, group2
```

## Troubleshooting

### If registered application is not multi-tenanted, how to run this sample?
In this auto-configuration, by [default](https://github.com/Microsoft/azure-spring-boot/blob/master/azure-spring-boot/src/main/resources/aad-oauth2-common.properties#L1-L4) `/common` is used for the tenant value. According to [Active Directory Sign In Request format](https://docs.microsoft.com/azure/active-directory/develop/v2-protocols-oidc#send-the-sign-in-request), if your application is not multi-tenanted, you have to configure a tenant specific authorization endpoints.

Configure endpoints with specific tenant-id by replacing `common` in your application.properties file:
```properties
spring.security.oauth2.client.provider.azure-oauth-provider.authorization-uri=https://login.microsoftonline.com/{your-tenant-id}/oauth2/authorize
spring.security.oauth2.client.provider.azure-oauth-provider.token-uri=https://login.microsoftonline.com/{your-tenant-id}/oauth2/token
spring.security.oauth2.client.provider.azure-oauth-provider.user-info-uri=https://login.microsoftonline.com/{your-tenant-id}/openid/userinfo
spring.security.oauth2.client.provider.azure-oauth-provider.jwk-set-uri=https://login.microsoftonline.com/{your-tenant-id}/discovery/keys
```
---
### Meet with `AADSTS240002: Input id_token cannot be used as 'urn:ietf:params:oauth:grant-type:jwt-bearer' grant` error.
In Azure portal, app registration manifest page, configure `oauth2AllowImplicitFlow` in your application manifest to `true`. See [this issue](https://github.com/MicrosoftDocs/azure-docs/issues/8121#issuecomment-387090099) for details on this workaround.

## Next steps
## Contributing
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should put standard text for contributing.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we link to this CONTRIBUTING.md?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This contributing guide is very specific to azure-sdk-for-java and its related tools. You probably want a guide which talks about how user can contribute to something which is specific to azure-spring-*

Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<parent>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-spring-boot-samples</artifactId>
<version>1.0.0</version>
<relativePath>../pom.xml</relativePath>
</parent>

<artifactId>azure-spring-boot-sample-active-directory-backend-v2</artifactId>
<packaging>jar</packaging>

<name>Azure AD Spring Security 5 OAuth2 V2 Integration Spring Boot Sample</name>
<description>Azure AD Spring Security 5 OAuth2 V2 Integration Spring Boot Sample</description>
<url>https://github.com/Azure/azure-sdk-for-java</url>

<dependencies>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-active-directory-spring-boot-starter</artifactId>
<version>2.2.5-beta.1</version> <!-- {x-version-update;com.microsoft.azure:azure-active-directory-spring-boot-starter;current} -->
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-oauth2-jose</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-springsecurity5</artifactId>
</dependency>
</dependencies>

</project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package microsoft.azure.aad;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class AzureADOAuth2V2BackendSampleApplication {

public static void main(String[] args) {
SpringApplication.run(AzureADOAuth2V2BackendSampleApplication.class, args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package microsoft.azure.aad.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClient;
import org.springframework.security.oauth2.client.OAuth2AuthorizedClientService;
import org.springframework.security.oauth2.client.authentication.OAuth2AuthenticationToken;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
public class HomeController {
@Autowired
private OAuth2AuthorizedClientService authorizedClientService;

@GetMapping("group1")
@ResponseBody
@PreAuthorize("hasRole('ROLE_group1')")
public String group1() {
return "group1 message";
}

@GetMapping("group2")
@ResponseBody
@PreAuthorize("hasRole('ROLE_group2')")
public String group2() {
return "group2 message";
}

@GetMapping("/")
public String index(Model model, OAuth2AuthenticationToken authentication) {
final OAuth2AuthorizedClient authorizedClient =
this.authorizedClientService.loadAuthorizedClient(
authentication.getAuthorizedClientRegistrationId(),
authentication.getName());
model.addAttribute("userName", authentication.getName());
model.addAttribute("clientName", authorizedClient.getClientRegistration().getClientName());
return "index";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package microsoft.azure.aad.security;

import com.microsoft.azure.spring.autoconfigure.aad.AADAuthenticationFailureHandler;
import com.microsoft.azure.spring.autoconfigure.aad.AADOAuth2AuthorizationRequestResolver;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.registration.ClientRegistrationRepository;
import org.springframework.security.oauth2.client.userinfo.OAuth2UserService;
import org.springframework.security.oauth2.core.oidc.user.OidcUser;

@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class AADOAuth2LoginSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private OAuth2UserService<OidcUserRequest, OidcUser> oidcUserService;

@Autowired
ApplicationContext applicationContext;

@Override
protected void configure(HttpSecurity http) throws Exception {
final ClientRegistrationRepository clientRegistrationRepository =
applicationContext.getBean(ClientRegistrationRepository.class);
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2Login()
.userInfoEndpoint()
.oidcUserService(oidcUserService)
.and()
.authorizationEndpoint()
.authorizationRequestResolver(
new AADOAuth2AuthorizationRequestResolver(clientRegistrationRepository))
.and()
.failureHandler(new AADAuthenticationFailureHandler());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
spring.security.oauth2.client.registration.azure.client-id=xxxxxx-your-client-id-xxxxxx
spring.security.oauth2.client.registration.azure.client-secret=xxxxxx-your-client-secret-xxxxxx

azure.activedirectory.tenant-id=xxxxxx-your-tenant-id-xxxxxx

# It's suggested the logged in user should at least belong to one of the below groups
# If not, the logged in user will not be able to access any authorization controller rest APIs
azure.activedirectory.active-directory-groups=group1, group2
azure.activedirectory.environment=global-v2-graph
azure.activedirectory.user-group.key=@odata.type
azure.activedirectory.user-group.value=#microsoft.graph.group
azure.activedirectory.user-group.object-id-key=id
Loading