BasicNegoziazioneTokenParser.java

  1. /*
  2.  * GovWay - A customizable API Gateway
  3.  * https://govway.org
  4.  *
  5.  * Copyright (c) 2005-2025 Link.it srl (https://link.it).
  6.  *
  7.  * This program is free software: you can redistribute it and/or modify
  8.  * it under the terms of the GNU General Public License version 3, as published by
  9.  * the Free Software Foundation.
  10.  *
  11.  * This program is distributed in the hope that it will be useful,
  12.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  * GNU General Public License for more details.
  15.  *
  16.  * You should have received a copy of the GNU General Public License
  17.  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  18.  *
  19.  */
  20. package org.openspcoop2.pdd.core.token.parser;

  21. import java.io.Serializable;
  22. import java.util.ArrayList;
  23. import java.util.Date;
  24. import java.util.List;
  25. import java.util.Map;
  26. import java.util.Properties;

  27. import org.apache.commons.lang.StringUtils;
  28. import org.openspcoop2.pdd.core.token.Costanti;
  29. import org.openspcoop2.pdd.core.token.TokenUtilities;
  30. import org.openspcoop2.utils.UtilsException;
  31. import org.openspcoop2.utils.date.DateManager;

  32. /**    
  33.  * BasicTokenParser
  34.  *
  35.  * @author Poli Andrea (poli@link.it)
  36.  * @author $Author$
  37.  * @version $Rev$, $Date$
  38.  */
  39. public class BasicNegoziazioneTokenParser implements INegoziazioneTokenParser {

  40.     protected Integer httpResponseCode;
  41.     protected String raw;
  42.     protected Map<String, Serializable> claims;
  43.     protected TipologiaClaimsNegoziazione parser;
  44.     protected Properties parserConfig;
  45.     protected Date now;
  46.    
  47.     public BasicNegoziazioneTokenParser(TipologiaClaimsNegoziazione parser) {
  48.         this(parser, null);
  49.     }
  50.     public BasicNegoziazioneTokenParser(TipologiaClaimsNegoziazione parser, Properties parserConfig) {
  51.         this.parser = parser;
  52.         this.parserConfig = parserConfig;
  53.     }
  54.    
  55.     @Override
  56.     public void init(String raw, Map<String, Serializable> claims) {
  57.         this.raw = raw;
  58.         this.claims = claims;
  59.         this.now = DateManager.getDate();
  60.     }

  61.    
  62.     @Override
  63.     public void checkHttpTransaction(Integer httpResponseCode) throws UtilsException{
  64.         this.httpResponseCode = httpResponseCode;
  65.         switch (this.parser) {
  66.         case OAUTH2_RFC_6749:
  67.         case MAPPING:
  68.         case RAW:
  69.         case CUSTOM:
  70.             if(this.httpResponseCode!=null &&
  71.                 (this.httpResponseCode.intValue() < 200 || this.httpResponseCode.intValue()>299)) {
  72.                 String msgError = "Connessione terminata con errore (codice trasporto: "+this.httpResponseCode.intValue()+")";
  73.                 throw new UtilsException(msgError+": "+this.raw);
  74.             }
  75.             break;
  76.         }
  77.     }
  78.    
  79.     @Override
  80.     public boolean isValid() {
  81.        
  82.         if(TipologiaClaimsNegoziazione.RAW.equals(this.parser)) {
  83.             if(this.raw==null || StringUtils.isEmpty(this.raw)) {
  84.                 return false;
  85.             }
  86.         }
  87.         else {
  88.             if(this.claims==null || this.claims.size()<=0) {
  89.                 return false;
  90.             }
  91.         }
  92.        
  93.         switch (this.parser) {
  94.         case OAUTH2_RFC_6749:
  95.             String claim = TokenUtilities.getClaimAsString(this.claims,ClaimsNegoziazione.OAUTH2_RFC_6749_ACCESS_TOKEN);
  96.             return !StringUtils.isEmpty(claim);
  97.         case MAPPING:
  98.             List<String> claimNames = TokenUtilities.getClaims(this.parserConfig, Costanti.RETRIEVE_TOKEN_PARSER_ACCESS_TOKEN);
  99.             if(claimNames==null || claimNames.isEmpty()) {
  100.                 return false;
  101.             }
  102.             claim = TokenUtilities.getFirstClaimAsString(this.claims, claimNames);
  103.             return !StringUtils.isEmpty(claim);
  104.         case RAW:
  105.         case CUSTOM:
  106.             return true;
  107.         }
  108.        
  109.         return false;
  110.     }
  111.    
  112.    
  113.     @Override
  114.     public String getAccessToken() {
  115.         switch (this.parser) {
  116.         case OAUTH2_RFC_6749:
  117.             String claim = TokenUtilities.getClaimAsString(this.claims,ClaimsNegoziazione.OAUTH2_RFC_6749_ACCESS_TOKEN);
  118.             return claim;
  119.         case MAPPING:
  120.             List<String> claimNames = TokenUtilities.getClaims(this.parserConfig, Costanti.RETRIEVE_TOKEN_PARSER_ACCESS_TOKEN);
  121.             return TokenUtilities.getFirstClaimAsString(this.claims, claimNames);
  122.         case RAW:
  123.             return this.raw;
  124.         case CUSTOM:
  125.             return null;
  126.         }
  127.         return null;
  128.     }

  129.     @Override
  130.     public String getRefreshToken() {
  131.         switch (this.parser) {
  132.         case OAUTH2_RFC_6749:
  133.             String claim = TokenUtilities.getClaimAsString(this.claims,ClaimsNegoziazione.OAUTH2_RFC_6749_REFRESH_TOKEN);
  134.             return claim;
  135.         case MAPPING:
  136.             List<String> claimNames = TokenUtilities.getClaims(this.parserConfig, Costanti.RETRIEVE_TOKEN_PARSER_REFRESH_TOKEN);
  137.             return TokenUtilities.getFirstClaimAsString(this.claims, claimNames);
  138.         case RAW:
  139.         case CUSTOM:
  140.             return null;
  141.         }
  142.         return null;
  143.     }

  144.     @Override
  145.     public String getTokenType() {
  146.         switch (this.parser) {
  147.         case OAUTH2_RFC_6749:
  148.             String claim = TokenUtilities.getClaimAsString(this.claims,ClaimsNegoziazione.OAUTH2_RFC_6749_TOKEN_TYPE);
  149.             return claim;
  150.         case MAPPING:
  151.             List<String> claimNames = TokenUtilities.getClaims(this.parserConfig, Costanti.RETRIEVE_TOKEN_PARSER_TOKEN_TYPE);
  152.             return TokenUtilities.getFirstClaimAsString(this.claims, claimNames);
  153.         case RAW:
  154.         case CUSTOM:
  155.             return null;
  156.         }
  157.         return null;
  158.     }
  159.    
  160.     @Override
  161.     public Date getExpired() {
  162.         String tmpIn = null;
  163.         String tmpOn = null;
  164.         switch (this.parser) {
  165.         case OAUTH2_RFC_6749:{
  166.             tmpIn =  TokenUtilities.getClaimAsString(this.claims,ClaimsNegoziazione.OAUTH2_RFC_6749_EXPIRES_IN);
  167.             if(tmpIn==null || StringUtils.isEmpty(tmpIn)) {
  168.                 tmpOn =  TokenUtilities.getClaimAsString(this.claims,ClaimsNegoziazione.AZURE_EXPIRES_ON);
  169.             }
  170.             break;
  171.         }
  172.         case MAPPING:{
  173.             tmpIn = parseMappingExpiresIn();
  174.             if(tmpIn==null || StringUtils.isEmpty(tmpIn)) {
  175.                 tmpOn = parseMappingExpiresOn();
  176.             }
  177.             break;
  178.         }
  179.         case RAW:{
  180.             List<String> claimNames = TokenUtilities.getClaims(this.parserConfig, Costanti.RETRIEVE_TOKEN_PARSER_EXPIRES_IN_SECONDS);
  181.             if(claimNames!=null && !claimNames.isEmpty()) {
  182.                 tmpIn = claimNames.get(0);
  183.             }
  184.             break;
  185.         }
  186.         case CUSTOM:
  187.             return null;
  188.         }
  189.        
  190.         return parseDate(tmpIn, tmpOn);
  191.     }
  192.     private String parseMappingExpiresIn() {
  193.         List<String> claimNames = TokenUtilities.getClaims(this.parserConfig, Costanti.RETRIEVE_TOKEN_PARSER_EXPIRES_IN);
  194.         if(claimNames!=null && !claimNames.isEmpty()) {
  195.             return TokenUtilities.getFirstClaimAsString(this.claims, claimNames);
  196.         }
  197.         return null;
  198.     }
  199.     private String parseMappingExpiresOn() {
  200.         List<String> claimNames = TokenUtilities.getClaims(this.parserConfig, Costanti.RETRIEVE_TOKEN_PARSER_EXPIRES_ON);
  201.         if(claimNames!=null && !claimNames.isEmpty()) {
  202.             return TokenUtilities.getFirstClaimAsString(this.claims, claimNames);
  203.         }
  204.         return null;
  205.     }

  206.    
  207.     @Override
  208.     public Date getRefreshExpired() {
  209.         String tmpIn = null;
  210.         String tmpOn = null;
  211.         switch (this.parser) {
  212.         case OAUTH2_RFC_6749:
  213.             tmpIn = parseOauth2RFC6749RefreshExpiresIn();
  214.             if(tmpIn==null || StringUtils.isEmpty(tmpIn)) {
  215.                 tmpOn = parseOauth2RFC6749RefreshExpiresOn();
  216.             }
  217.             break;
  218.            
  219.         case MAPPING:
  220.             tmpIn = parseMappingRefreshExpiresIn();
  221.             if(tmpIn==null || StringUtils.isEmpty(tmpIn)) {
  222.                 tmpOn = parseMappingRefreshExpiresOn();
  223.             }
  224.             break;
  225.            
  226.         case RAW:
  227.         case CUSTOM:
  228.             return null;
  229.         }
  230.        
  231.         return parseDate(tmpIn, tmpOn);
  232.     }
  233.     private String parseOauth2RFC6749RefreshExpiresIn() {
  234.         for (String claim : ClaimsNegoziazione.REFRESH_EXPIRE_IN_CUSTOM_CLAIMS) {
  235.             String tmpC =  TokenUtilities.getClaimAsString(this.claims, claim);
  236.             if(tmpC!=null && StringUtils.isNotEmpty(tmpC)) {
  237.                 return tmpC;
  238.             }
  239.         }
  240.         return null;
  241.     }
  242.     private String parseOauth2RFC6749RefreshExpiresOn() {
  243.         for (String claim : ClaimsNegoziazione.REFRESH_EXPIRE_ON_CUSTOM_CLAIMS) {
  244.             String tmpC =  TokenUtilities.getClaimAsString(this.claims, claim);
  245.             if(tmpC!=null && StringUtils.isNotEmpty(tmpC)) {
  246.                 return tmpC;
  247.             }
  248.         }
  249.         return null;
  250.     }
  251.     private String parseMappingRefreshExpiresIn() {
  252.         List<String> claimNames = TokenUtilities.getClaims(this.parserConfig, Costanti.RETRIEVE_TOKEN_PARSER_REFRESH_EXPIRES_IN);
  253.         if(claimNames!=null && !claimNames.isEmpty()) {
  254.             return TokenUtilities.getFirstClaimAsString(this.claims, claimNames);
  255.         }
  256.         return null;
  257.     }
  258.     private String parseMappingRefreshExpiresOn() {
  259.         List<String> claimNames = TokenUtilities.getClaims(this.parserConfig, Costanti.RETRIEVE_TOKEN_PARSER_REFRESH_EXPIRES_ON);
  260.         if(claimNames!=null && !claimNames.isEmpty()) {
  261.             return TokenUtilities.getFirstClaimAsString(this.claims, claimNames);
  262.         }
  263.         return null;
  264.     }
  265.    
  266.    
  267.     private Date parseDate(String tmpIn, String tmpOn) {
  268.         if(tmpIn!=null) {
  269.             // The lifetime in seconds of the access token.  For example, the value "3600" denotes that the access token will
  270.             // expire in one hour from the time the response was generated.
  271.             return TokenUtils.convertLifeTimeInSeconds(this.now, tmpIn);
  272.         }
  273.        
  274.         // provo a vedere se ci fosse un claim che indica la data di scadenza in forma https://www.rfc-editor.org/rfc/rfc7519#section-4.1.4
  275.         if(tmpOn!=null) {
  276.             return TokenUtils.parseTimeInSecond(tmpOn);
  277.         }
  278.        
  279.         return null;
  280.     }



  281.     @Override
  282.     public List<String> getScopes() {
  283.        
  284.         String tmpScopes = null;
  285.         if(TipologiaClaimsNegoziazione.OAUTH2_RFC_6749.equals(this.parser)) {
  286.             tmpScopes = TokenUtilities.getClaimAsString(this.claims,ClaimsNegoziazione.OAUTH2_RFC_6749_SCOPE);
  287.         }
  288.         else if(TipologiaClaimsNegoziazione.MAPPING.equals(this.parser)) {
  289.             return readMappingScopes();
  290.         }
  291.        
  292.         return readScope(tmpScopes);
  293.     }
  294.     public List<String> readMappingScopes() {
  295.         List<String> claimNames = TokenUtilities.getClaims(this.parserConfig, Costanti.RETRIEVE_TOKEN_PARSER_SCOPE);
  296.         List<String> tmpScopesList = TokenUtilities.getFirstClaimAsList(this.claims, claimNames);
  297.         List<String> lNull = null;
  298.         if(tmpScopesList!=null && !tmpScopesList.isEmpty()) {
  299.             return readMappingScopes(tmpScopesList);
  300.         }
  301.         else {
  302.             return lNull;
  303.         }
  304.     }
  305.     public List<String> readMappingScopes(List<String> tmpScopesList) {
  306.         List<String> scopes = new ArrayList<>();
  307.         for (String s : tmpScopesList) {
  308.             List<String> tmp = readScope(s);
  309.             if(tmp!=null && !tmp.isEmpty()) {
  310.                 for (String sTmp : tmp) {
  311.                     if(!scopes.contains(sTmp)) {
  312.                         scopes.add(sTmp);
  313.                     }
  314.                 }
  315.             }
  316.         }
  317.         return scopes;
  318.     }
  319.    
  320.     private List<String> readScope(String tmpScopes) {
  321.         List<String> lNull = null;
  322.         if(tmpScopes!=null) {
  323.             String [] tmpArray = tmpScopes.split(" ");
  324.             if(tmpArray!=null && tmpArray.length>0) {
  325.                 List<String> scopes = new ArrayList<>();
  326.                 for (int i = 0; i < tmpArray.length; i++) {
  327.                     scopes.add(tmpArray[i].trim());
  328.                 }
  329.                 return scopes;
  330.             }
  331.         }
  332.         return lNull;
  333.     }
  334.    
  335. }