View Javadoc
1   /*
2    * Copyright 2024 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.bremersee.spring.security.ldaptive.authentication;
18  
19  import java.util.Collection;
20  import java.util.Objects;
21  import java.util.Optional;
22  import java.util.stream.Collectors;
23  import java.util.stream.Stream;
24  import org.bremersee.ldaptive.LdaptiveEntryMapper;
25  import org.ldaptive.dn.Dn;
26  import org.ldaptive.dn.NameValue;
27  import org.ldaptive.dn.RDn;
28  
29  /**
30   * Converts a username (like 'foobar') into it's bind dn (like
31   * 'uid=foobar,ou=people,dc=example,dc=org').
32   *
33   * @author Christian Bremer
34   */
35  @FunctionalInterface
36  public interface UsernameToBindDnConverter {
37  
38    /**
39     * Converts a username (like 'foobar') into it's bind dn (like
40     * 'uid=foobar,ou=people,dc=example,dc=org').
41     *
42     * @param username the username
43     * @return the bind dn
44     */
45    String convert(String username);
46  
47    /**
48     * The type By user rdn attribute.
49     */
50    class ByUserRdnAttribute implements UsernameToBindDnConverter {
51  
52      private final LdaptiveAuthenticationProperties properties;
53  
54      /**
55       * Instantiates a new converter.
56       *
57       * @param properties the properties
58       */
59      public ByUserRdnAttribute(LdaptiveAuthenticationProperties properties) {
60        this.properties = Objects
61            .requireNonNull(properties, "Ldaptive authentication properties are required.");
62      }
63  
64      @Override
65      public String convert(String username) {
66        return Optional.ofNullable(properties.getUserBaseDn())
67            .map(baseDn -> LdaptiveEntryMapper
68                .createDn(properties.getUserRdnAttribute(), username, baseDn))
69            .orElseThrow(() -> new IllegalStateException(String
70                .format("Converting username %s to bind dn is not possible.", username)));
71      }
72    }
73  
74    /**
75     * Converts a username (like 'foobar') into it's (active directory) bind dn (like
76     * 'foobar@example.org').
77     *
78     * @author Christian Bremer
79     */
80    class ByDomainEmail implements UsernameToBindDnConverter {
81  
82      private final LdaptiveAuthenticationProperties properties;
83  
84      /**
85       * Instantiates a new converter.
86       *
87       * @param properties the properties
88       */
89      public ByDomainEmail(LdaptiveAuthenticationProperties properties) {
90        this.properties = Objects
91            .requireNonNull(properties, "Ldaptive authentication properties are required.");
92      }
93  
94      @Override
95      public String convert(String username) {
96        return Optional.of(extractDomainName(properties.getUserBaseDn()))
97            .filter(domain -> !domain.isEmpty())
98            .map(domain -> username + "@" + domain)
99            .orElseThrow(() -> new IllegalStateException(String
100               .format("Converting username %s to bind dn is not possible.", username)));
101     }
102 
103     private static String extractDomainName(String baseDn) {
104       return Stream.ofNullable(baseDn)
105           .map(Dn::new)
106           .map(Dn::getRDns)
107           .flatMap(Collection::stream)
108           .map(RDn::getNameValue)
109           .filter(nameValue -> nameValue.hasName("dc"))
110           .map(NameValue::getStringValue)
111           .collect(Collectors.joining("."));
112     }
113 
114   }
115 
116 }