You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2022/10/25 19:00:04 UTC
[camel-spring-boot-examples] branch main updated: Added Microsoft Exchange IMAP Oauth2 Authentication example (#96)
This is an automated email from the ASF dual-hosted git repository.
davsclaus pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-spring-boot-examples.git
The following commit(s) were added to refs/heads/main by this push:
new 7858311 Added Microsoft Exchange IMAP Oauth2 Authentication example (#96)
7858311 is described below
commit 78583119d6cec15a89b2727bbf15fb109442aedd
Author: Luigi De Masi <55...@users.noreply.github.com>
AuthorDate: Tue Oct 25 20:59:58 2022 +0200
Added Microsoft Exchange IMAP Oauth2 Authentication example (#96)
---
mail-ms-exchange-oauth2/Readme.adoc | 64 ++++++++++++
mail-ms-exchange-oauth2/pom.xml | 111 +++++++++++++++++++++
.../mail/oauth2/ApplicationConfiguration.java | 109 ++++++++++++++++++++
.../example/mail/oauth2/CamelApplication.java | 64 ++++++++++++
.../oauth2/Oauth2ExchangeMailAuthenticator.java | 82 +++++++++++++++
.../src/main/resources/application.properties | 43 ++++++++
pom.xml | 1 +
7 files changed, 474 insertions(+)
diff --git a/mail-ms-exchange-oauth2/Readme.adoc b/mail-ms-exchange-oauth2/Readme.adoc
new file mode 100644
index 0000000..f12c6ef
--- /dev/null
+++ b/mail-ms-exchange-oauth2/Readme.adoc
@@ -0,0 +1,64 @@
+== Camel Spring Boot Microsoft Exchange IMAP Oauth2 Authentication
+
+This is an example that shows how to use Camel on Spring Boot to connect with
+IMAP protocol and access email data for Office 365 users using OAuth2 authentication.
+
+The application will use the client credentials grant flow to get the access token
+and use it to authenticate IMAP connections.
+
+
+=== Prerequisite
+
+* To use OAuth, an application must be registered with Azure Active Directory.
+Follow the instructions listed in https://learn.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-app[Register an application with the Microsoft identity platform] to register a new application.
+
+* Enable application to access Exchange mailboxes via client credentials flow adding *IMAP.AccessAsApp* permission. Instructions https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth#add-the-pop-and-imap-permissions-to-your-aad-application[here]
+
+* Create and register your Azure Active Directory application's service principal
+in Exchange via Exchange Online PowerShell. Instructions https://learn.microsoft.com/en-us/exchange/client-developer/legacy-protocols/how-to-authenticate-an-imap-pop-smtp-application-by-using-oauth#register-service-principals-in-exchange[here]
+
+* Edit the link:src/main/resources/application.properties[application.properties] adding the values to the properties marked with ``<FILL-ME>`` tag
+
+=== How to run
+
+You can run this example using:
+
+[source%nowrap, console]
+----
+mvn spring-boot:run
+----
+And you should see this output:
+
+[source%nowrap, console]
+----
+ . ____ _ __ _ _
+ /\\ / ___'_ __ _ _(_)_ __ __ _ \ \ \ \
+( ( )\___ | '_ | '_| | '_ \/ _` | \ \ \ \
+ \\/ ___)| |_)| | | | | || (_| | ) ) ) )
+ ' |____| .__|_| |_|_| |_\__, | / / / /
+ =========|_|==============|___/=/_/_/_/
+ :: Spring Boot :: (v2.7.5)
+
+2022-10-24 19:19:58.705 INFO 2274709 --- [ main] o.a.c.e.mail.oauth2.CamelApplication : Starting CamelApplication
+2022-10-24 19:19:58.707 INFO 2274709 --- [ main] o.a.c.e.mail.oauth2.CamelApplication : No active profile set, falling back to 1 default profile: "default"
+2022-10-24 19:20:00.777 INFO 2274709 --- [ main] o.a.c.impl.engine.AbstractCamelContext : Apache Camel is starting
+2022-10-24 19:20:00.785 INFO 2274709 --- [ main] c.s.b.CamelSpringBootApplicationListener : Starting CamelMainRunController to ensure the main thread keeps running
+2022-10-24 19:20:00.785 INFO 2274709 --- [inRunController] org.apache.camel.main.MainSupport : Apache Camel (Main) is starting
+2022-10-24 19:20:00.813 INFO 2274709 --- [ main] o.a.c.impl.engine.AbstractCamelContext : Routes startup (started:1)
+2022-10-24 19:20:00.813 INFO 2274709 --- [ main] o.a.c.impl.engine.AbstractCamelContext : Started camel-mail-ms-exchange (imaps://outlook.office365.com:993)
+2022-10-24 19:20:00.813 INFO 2274709 --- [ main] o.a.c.impl.engine.AbstractCamelContext : Apache Camel (CamelMailExchangeOAuth2) started in 1s226ms (build:29ms init:1s163ms start:34ms)
+2022-10-24 19:20:00.819 INFO 2274709 --- [ main] o.a.c.e.mail.oauth2.CamelApplication : Started CamelApplication in 2.407 seconds (JVM running for 2.883)
+2022-10-24 19:20:04.842 INFO 2274709 --- [fice365.com:993] camel-mail-ms-exchange : message Received:
+From: John Doe <jd...@example.com>
+Subj: Test
+Body:
+This is a Test!!!
+
+2022-10-24 19:20:05.167 INFO 2274709 --- [fice365.com:993] camel-mail-ms-exchange : message Received:
+From: Teigan Moore <te...@xyz.com>
+Subj: Prova
+Body:
+Prova Prova Prova
+--
+Teigan Moore
+----
\ No newline at end of file
diff --git a/mail-ms-exchange-oauth2/pom.xml b/mail-ms-exchange-oauth2/pom.xml
new file mode 100644
index 0000000..67b0b4b
--- /dev/null
+++ b/mail-ms-exchange-oauth2/pom.xml
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>examples</artifactId>
+ <groupId>org.apache.camel.springboot.example</groupId>
+ <version>3.20.0-SNAPSHOT</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <artifactId>camel-example-spring-boot-mail-exchange-oauth2</artifactId>
+ <packaging>jar</packaging>
+
+ <name>Camel SB Examples :: Mail :: Microsoft Exchange Oauth2 Authentication</name>
+ <description>An example showing how to use Camel on Spring Boot to connect
+ with IMAP protocol and access email data for Office 365 users using OAuth2 authentication</description>
+
+ <properties>
+ <maven.compiler.source>11</maven.compiler.source>
+ <maven.compiler.target>11</maven.compiler.target>
+ <msal4j-version>1.13.2</msal4j-version>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <!-- Spring Boot BOM -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-dependencies</artifactId>
+ <version>${spring-boot-version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ <!-- Camel BOM -->
+ <dependency>
+ <groupId>org.apache.camel.springboot</groupId>
+ <artifactId>camel-spring-boot-bom</artifactId>
+ <version>${camel-version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+
+ <!-- Spring Boot -->
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-starter-validation</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-configuration-processor</artifactId>
+ <optional>true</optional>
+ </dependency>
+
+ <!-- Camel -->
+ <dependency>
+ <groupId>org.apache.camel.springboot</groupId>
+ <artifactId>camel-spring-boot-starter</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.springboot</groupId>
+ <artifactId>camel-mail-starter</artifactId>
+ </dependency>
+
+ <!--Microsoft Authentication Library for Java -->
+ <dependency>
+ <groupId>com.microsoft.azure</groupId>
+ <artifactId>msal4j</artifactId>
+ <version>${msal4j-version}</version>
+ </dependency>
+
+ </dependencies>
+
+
+ <build>
+ <!-- we do not want version in the JAR name -->
+ <finalName>${project.artifactId}</finalName>
+ <plugins>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <version>${spring-boot-version}</version>
+ <configuration>
+ <mainClass>
+ org.apache.camel.example.mail.oauth2.CamelApplication
+ </mainClass>
+ </configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>repackage</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
\ No newline at end of file
diff --git a/mail-ms-exchange-oauth2/src/main/java/org/apache/camel/example/mail/oauth2/ApplicationConfiguration.java b/mail-ms-exchange-oauth2/src/main/java/org/apache/camel/example/mail/oauth2/ApplicationConfiguration.java
new file mode 100644
index 0000000..5828fa5
--- /dev/null
+++ b/mail-ms-exchange-oauth2/src/main/java/org/apache/camel/example/mail/oauth2/ApplicationConfiguration.java
@@ -0,0 +1,109 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example.mail.oauth2;
+
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.validation.annotation.Validated;
+
+import javax.validation.constraints.Email;
+import javax.validation.constraints.Min;
+import javax.validation.constraints.NotEmpty;
+
+@Validated
+@Configuration
+@ConfigurationProperties(prefix = "exchange")
+public class ApplicationConfiguration {
+
+ @NotEmpty
+ private String tenantId;
+
+ @NotEmpty
+ private String clientId;
+
+ @NotEmpty
+ private String clientSecret;
+
+ @Email
+ @NotEmpty
+ private String user;
+
+ @Min(1)
+ private long pollInterval = 60000;
+
+ private boolean debug = false;
+
+ private boolean delete = false;
+
+
+
+ public String getTenantId() {
+ return tenantId;
+ }
+
+ public void setTenantId(String tenantId) {
+ this.tenantId = tenantId;
+ }
+
+ public String getClientId() {
+ return clientId;
+ }
+
+ public void setClientId(String clientId) {
+ this.clientId = clientId;
+ }
+
+ public String getClientSecret() {
+ return clientSecret;
+ }
+
+ public void setClientSecret(String clientSecret) {
+ this.clientSecret = clientSecret;
+ }
+
+ public String getUser() {
+ return user;
+ }
+
+ public void setUser(String user) {
+ this.user = user;
+ }
+
+ public long getPollInterval() {
+ return pollInterval;
+ }
+
+ public void setPollInterval(long pollInterval) {
+ this.pollInterval = pollInterval;
+ }
+
+ public boolean isDebug() {
+ return debug;
+ }
+
+ public void setDebug(boolean debug) {
+ this.debug = debug;
+ }
+
+ public boolean isDelete() {
+ return delete;
+ }
+
+ public void setDelete(boolean delete) {
+ this.delete = delete;
+ }
+}
diff --git a/mail-ms-exchange-oauth2/src/main/java/org/apache/camel/example/mail/oauth2/CamelApplication.java b/mail-ms-exchange-oauth2/src/main/java/org/apache/camel/example/mail/oauth2/CamelApplication.java
new file mode 100644
index 0000000..0e6a6a5
--- /dev/null
+++ b/mail-ms-exchange-oauth2/src/main/java/org/apache/camel/example/mail/oauth2/CamelApplication.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example.mail.oauth2;
+
+import org.apache.camel.LoggingLevel;
+import org.apache.camel.builder.RouteBuilder;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.context.annotation.Bean;
+
+
+@SpringBootApplication
+@EnableConfigurationProperties
+public class CamelApplication {
+
+ @Autowired
+ ApplicationConfiguration conf;
+
+ /**
+ * A main method to start this application.
+ */
+ public static void main(String[] args) {
+ SpringApplication.run(CamelApplication.class, args);
+ }
+
+ @Bean
+ public Oauth2ExchangeMailAuthenticator exchangeAuthenticator(){
+ return new Oauth2ExchangeMailAuthenticator(conf.getTenantId(),conf.getClientId(), conf.getClientSecret(), conf.getUser());
+ }
+
+ @Bean
+ public RouteBuilder routeBuilder(){
+ return new RouteBuilder() {
+ @Override
+ public void configure() throws Exception {
+ from("imaps://outlook.office365.com:993?" +
+ "delay="+conf.getPollInterval()+"}&" +
+ "authenticator=#exchangeAuthenticator&" +
+ "mail.imaps.auth.mechanisms=XOAUTH2&" +
+ "debugMode="+conf.isDebug()+"&" +
+ "delete="+conf.isDelete()+"&"+
+ "bridgeErrorHandler=true")
+ .id("camel-mail-ms-exchange")
+ .log(LoggingLevel.INFO, "message Received: \nFrom: ${header.from}\nSubj: ${header.subject}\nBody:\n${body}");
+ }
+ };
+ }
+}
diff --git a/mail-ms-exchange-oauth2/src/main/java/org/apache/camel/example/mail/oauth2/Oauth2ExchangeMailAuthenticator.java b/mail-ms-exchange-oauth2/src/main/java/org/apache/camel/example/mail/oauth2/Oauth2ExchangeMailAuthenticator.java
new file mode 100644
index 0000000..b0eac99
--- /dev/null
+++ b/mail-ms-exchange-oauth2/src/main/java/org/apache/camel/example/mail/oauth2/Oauth2ExchangeMailAuthenticator.java
@@ -0,0 +1,82 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.example.mail.oauth2;
+
+import com.microsoft.aad.msal4j.ClientCredentialFactory;
+import com.microsoft.aad.msal4j.ClientCredentialParameters;
+import com.microsoft.aad.msal4j.ConfidentialClientApplication;
+import com.microsoft.aad.msal4j.IAuthenticationResult;
+import com.microsoft.aad.msal4j.IClientCredential;
+import org.apache.camel.component.mail.MailAuthenticator;
+
+import javax.mail.PasswordAuthentication;
+import java.net.MalformedURLException;
+import java.util.Collections;
+import java.util.Set;
+
+
+public class Oauth2ExchangeMailAuthenticator extends MailAuthenticator {
+ private static final Set<String> SCOPE = Collections.singleton("https://outlook.office365.com/.default");
+ private static final String AUTHORITY_BASE_URL = "https://login.microsoftonline.com/";
+ private final String clientId;
+ private final String clientSecret;
+ private final String authority;
+ private final String user;
+
+
+ public Oauth2ExchangeMailAuthenticator(String tenantId, String clientId, String clientSecret, String user) {
+ this.clientId = clientId;
+ this.clientSecret = clientSecret;
+ this.authority = AUTHORITY_BASE_URL + tenantId;
+ this.user = user;
+ }
+
+ @Override
+ public PasswordAuthentication getPasswordAuthentication() {
+ String accessToken = acquireToken();
+ return new PasswordAuthentication(user, accessToken);
+ }
+
+ private String acquireToken() {
+
+ ConfidentialClientApplication cca;
+ try {
+ // This is the secret that is created in the Azure portal when registering the application
+ IClientCredential credential = ClientCredentialFactory.createFromSecret(clientSecret);
+
+ cca = ConfidentialClientApplication
+ .builder(clientId, credential)
+ .authority(authority)
+ .build();
+ } catch (MalformedURLException e) {
+ throw new RuntimeException(e);
+ }
+
+ // Client credential requests will by default try to look for a valid token in the
+ // in-memory token cache. If found, it will return this token. If a token is not found, or the
+ // token is not valid, it will fall back to acquiring a token from the AAD service. Although
+ // not recommended unless there is a reason for doing so, you can skip the cache lookup
+ // by using .skipCache(true) in ClientCredentialParameters.
+ ClientCredentialParameters parameters =
+ ClientCredentialParameters
+ .builder(SCOPE)
+ .build();
+
+ IAuthenticationResult result = cca.acquireToken(parameters).join();
+ return result.accessToken();
+ }
+}
diff --git a/mail-ms-exchange-oauth2/src/main/resources/application.properties b/mail-ms-exchange-oauth2/src/main/resources/application.properties
new file mode 100644
index 0000000..84446b0
--- /dev/null
+++ b/mail-ms-exchange-oauth2/src/main/resources/application.properties
@@ -0,0 +1,43 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+camel.springboot.name: CamelMailExchangeOAuth2
+
+# Keep the application running
+camel.springboot.main-run-controller: true
+
+
+# Azure Active Directory tenant ID
+exchange.tenantId=<FILL-ME>
+
+# Azure Active Directory client credentials
+exchange.clientId=<FILL-ME>
+
+# Azure Active Directory client secret
+exchange.clientSecret=<FILL-ME>
+
+# Microsoft Exchange Username. Must be an email.
+exchange.user=<FILL-ME>
+
+# Milliseconds between two poll.
+exchange.pollInterval=60000
+
+# Enable javax.mail verbose output
+exchange.debug=false
+
+# Delete message after consuming it
+exchange.delete=false
diff --git a/pom.xml b/pom.xml
index b246620..9baca7d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -58,6 +58,7 @@
<module>kafka-offsetrepository</module>
<module>kamelet-chucknorris</module>
<module>load-balancer-eip</module>
+ <module>mail-ms-exchange-oauth2</module>
<module>master</module>
<module>metrics</module>
<module>opentracing</module>