View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.syncope.core.spring.security.jws;
20  
21  import com.nimbusds.jose.JOSEException;
22  import com.nimbusds.jose.JWSAlgorithm;
23  import com.nimbusds.jose.JWSHeader;
24  import com.nimbusds.jose.JWSSigner;
25  import com.nimbusds.jose.KeyLengthException;
26  import com.nimbusds.jose.crypto.MACSigner;
27  import com.nimbusds.jose.crypto.RSASSASigner;
28  import com.nimbusds.jose.jca.JCAContext;
29  import com.nimbusds.jose.util.Base64URL;
30  import java.security.KeyFactory;
31  import java.security.NoSuchAlgorithmException;
32  import java.security.spec.InvalidKeySpecException;
33  import java.security.spec.PKCS8EncodedKeySpec;
34  import java.util.Base64;
35  import java.util.Set;
36  import org.apache.commons.lang3.StringUtils;
37  
38  public class AccessTokenJWSSigner implements JWSSigner {
39  
40      private final JWSAlgorithm jwsAlgorithm;
41  
42      private final JWSSigner delegate;
43  
44      public AccessTokenJWSSigner(final JWSAlgorithm jwsAlgorithm, final String jwsKey)
45              throws KeyLengthException, NoSuchAlgorithmException, InvalidKeySpecException {
46  
47          this.jwsAlgorithm = jwsAlgorithm;
48  
49          if (JWSAlgorithm.Family.RSA.contains(jwsAlgorithm)) {
50              if (jwsKey.indexOf(':') == -1) {
51                  throw new IllegalArgumentException("A key pair is required, in the 'private:public' format");
52              }
53  
54              KeyFactory kf = KeyFactory.getInstance("RSA");
55              PKCS8EncodedKeySpec keySpecPKCS8 = new PKCS8EncodedKeySpec(
56                      Base64.getDecoder().decode(StringUtils.substringBefore(jwsKey, ":").getBytes()));
57              delegate = new RSASSASigner(kf.generatePrivate(keySpecPKCS8));
58          } else if (JWSAlgorithm.Family.HMAC_SHA.contains(jwsAlgorithm)) {
59              delegate = new MACSigner(jwsKey);
60          } else {
61              throw new IllegalArgumentException("Unsupported JWS algorithm: " + jwsAlgorithm.getName());
62          }
63      }
64  
65      public JWSAlgorithm getJwsAlgorithm() {
66          return jwsAlgorithm;
67      }
68  
69      @Override
70      public Set<JWSAlgorithm> supportedJWSAlgorithms() {
71          return delegate.supportedJWSAlgorithms();
72      }
73  
74      @Override
75      public JCAContext getJCAContext() {
76          return delegate.getJCAContext();
77      }
78  
79      @Override
80      public Base64URL sign(final JWSHeader header, final byte[] signingInput) throws JOSEException {
81          return delegate.sign(header, signingInput);
82      }
83  }