1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.fit.core.reference;
20
21 import com.nimbusds.jose.JOSEException;
22 import com.nimbusds.jose.JWSAlgorithm;
23 import com.nimbusds.jose.JWSHeader;
24 import com.nimbusds.jose.JWSVerifier;
25 import com.nimbusds.jose.crypto.MACVerifier;
26 import com.nimbusds.jose.jca.JCAContext;
27 import com.nimbusds.jose.util.Base64URL;
28 import com.nimbusds.jwt.JWTClaimsSet;
29 import java.util.List;
30 import java.util.Set;
31 import org.apache.commons.lang3.tuple.Pair;
32 import org.apache.syncope.common.lib.types.AnyTypeKind;
33 import org.apache.syncope.core.persistence.api.dao.AnySearchDAO;
34 import org.apache.syncope.core.persistence.api.dao.search.AttrCond;
35 import org.apache.syncope.core.persistence.api.dao.search.SearchCond;
36 import org.apache.syncope.core.persistence.api.entity.user.User;
37 import org.apache.syncope.core.spring.security.AuthDataAccessor;
38 import org.apache.syncope.core.spring.security.JWTSSOProvider;
39 import org.apache.syncope.core.spring.security.SyncopeGrantedAuthority;
40 import org.springframework.transaction.annotation.Transactional;
41
42
43
44
45 public class CustomJWTSSOProvider implements JWTSSOProvider {
46
47 public static final String ISSUER = "custom-issuer";
48
49 public static final String CUSTOM_KEY =
50 "XW3eTdntLa9Zsz2t4Vm6TNUya8xJEezFS7NVD3ZIZKOMdmSPMfi40rIvyBzXdbqD7TTsp6grcVW3AvRhZnFzZNaLdp6kJ2HXU9X9t2arVK"
51 + "42bIAp7XOw6aZg8v4OOXReZ9YkuAKtGwKC1JvPMKCz0c28AhJWd3YX5MpG6prXExQpFFVuweA6xTPxf06nYEFSOmKJ9ddJAcIx4Z8qyY"
52 + "mDJyNscMU8eVVM7aCR9zrCAHnjRZI2i6OnStAEVuqfGL25tK9AUKPVvyWljHNZ6ugXkstF873QaYJTBst1U2Zl9XsZnyeKrFEwwVHipp"
53 + "vfHwo2xu6VKySyJpZtaqVrjXFqpgFGRwEm890tCm8JhEG6GgJPqcnFHrYC180LqBZSjnNQGvA7eCSFVrABWcWnXDJCIHWbn0Wv153Vf4"
54 + "ZH75XEEYY53KsOS2T2GAmoqV3Izz7RL8O5dntgNLevl5gZb6MbYFURnQt0vALeObxMmv459FsXinzpAVihriOZWAudpN6Q";
55
56 private final JWSVerifier delegate;
57
58 private final AnySearchDAO anySearchDAO;
59
60 private final AuthDataAccessor authDataAccessor;
61
62 public CustomJWTSSOProvider(
63 final AnySearchDAO anySearchDAO,
64 final AuthDataAccessor authDataAccessor)
65 throws JOSEException {
66
67 this.delegate = new MACVerifier(CUSTOM_KEY);
68 this.anySearchDAO = anySearchDAO;
69 this.authDataAccessor = authDataAccessor;
70 }
71
72 @Override
73 public String getIssuer() {
74 return ISSUER;
75 }
76
77 @Override
78 public Set<JWSAlgorithm> supportedJWSAlgorithms() {
79 return delegate.supportedJWSAlgorithms();
80 }
81
82 @Override
83 public JCAContext getJCAContext() {
84 return delegate.getJCAContext();
85 }
86
87 @Override
88 public boolean verify(
89 final JWSHeader header,
90 final byte[] signingInput,
91 final Base64URL signature) throws JOSEException {
92
93 return delegate.verify(header, signingInput, signature);
94 }
95
96 @Transactional(readOnly = true)
97 @Override
98 public Pair<User, Set<SyncopeGrantedAuthority>> resolve(final JWTClaimsSet jwtClaims) {
99 AttrCond userIdCond = new AttrCond();
100 userIdCond.setSchema("userId");
101 userIdCond.setType(AttrCond.Type.EQ);
102 userIdCond.setExpression(jwtClaims.getSubject());
103
104 List<User> matching = anySearchDAO.search(SearchCond.getLeaf(userIdCond), AnyTypeKind.USER);
105 if (matching.size() == 1) {
106 User user = matching.get(0);
107 Set<SyncopeGrantedAuthority> authorities = authDataAccessor.getAuthorities(user.getUsername(), null);
108
109 return Pair.of(user, authorities);
110 }
111
112 return null;
113 }
114 }