BasicNegoziazioneTokenParser.java
/*
* GovWay - A customizable API Gateway
* https://govway.org
*
* Copyright (c) 2005-2024 Link.it srl (https://link.it).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3, as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.openspcoop2.pdd.core.token.parser;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import org.apache.commons.lang.StringUtils;
import org.openspcoop2.pdd.core.token.Costanti;
import org.openspcoop2.pdd.core.token.TokenUtilities;
import org.openspcoop2.utils.UtilsException;
import org.openspcoop2.utils.date.DateManager;
/**
* BasicTokenParser
*
* @author Poli Andrea (poli@link.it)
* @author $Author$
* @version $Rev$, $Date$
*/
public class BasicNegoziazioneTokenParser implements INegoziazioneTokenParser {
protected Integer httpResponseCode;
protected String raw;
protected Map<String, Serializable> claims;
protected TipologiaClaimsNegoziazione parser;
protected Properties parserConfig;
protected Date now;
public BasicNegoziazioneTokenParser(TipologiaClaimsNegoziazione parser) {
this(parser, null);
}
public BasicNegoziazioneTokenParser(TipologiaClaimsNegoziazione parser, Properties parserConfig) {
this.parser = parser;
this.parserConfig = parserConfig;
}
@Override
public void init(String raw, Map<String, Serializable> claims) {
this.raw = raw;
this.claims = claims;
this.now = DateManager.getDate();
}
@Override
public void checkHttpTransaction(Integer httpResponseCode) throws UtilsException{
this.httpResponseCode = httpResponseCode;
switch (this.parser) {
case OAUTH2_RFC_6749:
case MAPPING:
case RAW:
case CUSTOM:
if(this.httpResponseCode!=null &&
(this.httpResponseCode.intValue() < 200 || this.httpResponseCode.intValue()>299)) {
String msgError = "Connessione terminata con errore (codice trasporto: "+this.httpResponseCode.intValue()+")";
throw new UtilsException(msgError+": "+this.raw);
}
break;
}
}
@Override
public boolean isValid() {
if(TipologiaClaimsNegoziazione.RAW.equals(this.parser)) {
if(this.raw==null || StringUtils.isEmpty(this.raw)) {
return false;
}
}
else {
if(this.claims==null || this.claims.size()<=0) {
return false;
}
}
switch (this.parser) {
case OAUTH2_RFC_6749:
String claim = TokenUtilities.getClaimAsString(this.claims,ClaimsNegoziazione.OAUTH2_RFC_6749_ACCESS_TOKEN);
return !StringUtils.isEmpty(claim);
case MAPPING:
List<String> claimNames = TokenUtilities.getClaims(this.parserConfig, Costanti.RETRIEVE_TOKEN_PARSER_ACCESS_TOKEN);
if(claimNames==null || claimNames.isEmpty()) {
return false;
}
claim = TokenUtilities.getFirstClaimAsString(this.claims, claimNames);
return !StringUtils.isEmpty(claim);
case RAW:
case CUSTOM:
return true;
}
return false;
}
@Override
public String getAccessToken() {
switch (this.parser) {
case OAUTH2_RFC_6749:
String claim = TokenUtilities.getClaimAsString(this.claims,ClaimsNegoziazione.OAUTH2_RFC_6749_ACCESS_TOKEN);
return claim;
case MAPPING:
List<String> claimNames = TokenUtilities.getClaims(this.parserConfig, Costanti.RETRIEVE_TOKEN_PARSER_ACCESS_TOKEN);
return TokenUtilities.getFirstClaimAsString(this.claims, claimNames);
case RAW:
return this.raw;
case CUSTOM:
return null;
}
return null;
}
@Override
public String getRefreshToken() {
switch (this.parser) {
case OAUTH2_RFC_6749:
String claim = TokenUtilities.getClaimAsString(this.claims,ClaimsNegoziazione.OAUTH2_RFC_6749_REFRESH_TOKEN);
return claim;
case MAPPING:
List<String> claimNames = TokenUtilities.getClaims(this.parserConfig, Costanti.RETRIEVE_TOKEN_PARSER_REFRESH_TOKEN);
return TokenUtilities.getFirstClaimAsString(this.claims, claimNames);
case RAW:
case CUSTOM:
return null;
}
return null;
}
@Override
public String getTokenType() {
switch (this.parser) {
case OAUTH2_RFC_6749:
String claim = TokenUtilities.getClaimAsString(this.claims,ClaimsNegoziazione.OAUTH2_RFC_6749_TOKEN_TYPE);
return claim;
case MAPPING:
List<String> claimNames = TokenUtilities.getClaims(this.parserConfig, Costanti.RETRIEVE_TOKEN_PARSER_TOKEN_TYPE);
return TokenUtilities.getFirstClaimAsString(this.claims, claimNames);
case RAW:
case CUSTOM:
return null;
}
return null;
}
@Override
public Date getExpired() {
String tmpIn = null;
String tmpOn = null;
switch (this.parser) {
case OAUTH2_RFC_6749:{
tmpIn = TokenUtilities.getClaimAsString(this.claims,ClaimsNegoziazione.OAUTH2_RFC_6749_EXPIRES_IN);
if(tmpIn==null || StringUtils.isEmpty(tmpIn)) {
tmpOn = TokenUtilities.getClaimAsString(this.claims,ClaimsNegoziazione.AZURE_EXPIRES_ON);
}
break;
}
case MAPPING:{
tmpIn = parseMappingExpiresIn();
if(tmpIn==null || StringUtils.isEmpty(tmpIn)) {
tmpOn = parseMappingExpiresOn();
}
break;
}
case RAW:{
List<String> claimNames = TokenUtilities.getClaims(this.parserConfig, Costanti.RETRIEVE_TOKEN_PARSER_EXPIRES_IN_SECONDS);
if(claimNames!=null && !claimNames.isEmpty()) {
tmpIn = claimNames.get(0);
}
break;
}
case CUSTOM:
return null;
}
return parseDate(tmpIn, tmpOn);
}
private String parseMappingExpiresIn() {
List<String> claimNames = TokenUtilities.getClaims(this.parserConfig, Costanti.RETRIEVE_TOKEN_PARSER_EXPIRES_IN);
if(claimNames!=null && !claimNames.isEmpty()) {
return TokenUtilities.getFirstClaimAsString(this.claims, claimNames);
}
return null;
}
private String parseMappingExpiresOn() {
List<String> claimNames = TokenUtilities.getClaims(this.parserConfig, Costanti.RETRIEVE_TOKEN_PARSER_EXPIRES_ON);
if(claimNames!=null && !claimNames.isEmpty()) {
return TokenUtilities.getFirstClaimAsString(this.claims, claimNames);
}
return null;
}
@Override
public Date getRefreshExpired() {
String tmpIn = null;
String tmpOn = null;
switch (this.parser) {
case OAUTH2_RFC_6749:
tmpIn = parseOauth2RFC6749RefreshExpiresIn();
if(tmpIn==null || StringUtils.isEmpty(tmpIn)) {
tmpOn = parseOauth2RFC6749RefreshExpiresOn();
}
break;
case MAPPING:
tmpIn = parseMappingRefreshExpiresIn();
if(tmpIn==null || StringUtils.isEmpty(tmpIn)) {
tmpOn = parseMappingRefreshExpiresOn();
}
break;
case RAW:
case CUSTOM:
return null;
}
return parseDate(tmpIn, tmpOn);
}
private String parseOauth2RFC6749RefreshExpiresIn() {
for (String claim : ClaimsNegoziazione.REFRESH_EXPIRE_IN_CUSTOM_CLAIMS) {
String tmpC = TokenUtilities.getClaimAsString(this.claims, claim);
if(tmpC!=null && StringUtils.isNotEmpty(tmpC)) {
return tmpC;
}
}
return null;
}
private String parseOauth2RFC6749RefreshExpiresOn() {
for (String claim : ClaimsNegoziazione.REFRESH_EXPIRE_ON_CUSTOM_CLAIMS) {
String tmpC = TokenUtilities.getClaimAsString(this.claims, claim);
if(tmpC!=null && StringUtils.isNotEmpty(tmpC)) {
return tmpC;
}
}
return null;
}
private String parseMappingRefreshExpiresIn() {
List<String> claimNames = TokenUtilities.getClaims(this.parserConfig, Costanti.RETRIEVE_TOKEN_PARSER_REFRESH_EXPIRES_IN);
if(claimNames!=null && !claimNames.isEmpty()) {
return TokenUtilities.getFirstClaimAsString(this.claims, claimNames);
}
return null;
}
private String parseMappingRefreshExpiresOn() {
List<String> claimNames = TokenUtilities.getClaims(this.parserConfig, Costanti.RETRIEVE_TOKEN_PARSER_REFRESH_EXPIRES_ON);
if(claimNames!=null && !claimNames.isEmpty()) {
return TokenUtilities.getFirstClaimAsString(this.claims, claimNames);
}
return null;
}
private Date parseDate(String tmpIn, String tmpOn) {
if(tmpIn!=null) {
// The lifetime in seconds of the access token. For example, the value "3600" denotes that the access token will
// expire in one hour from the time the response was generated.
return TokenUtils.convertLifeTimeInSeconds(this.now, tmpIn);
}
// 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
if(tmpOn!=null) {
return TokenUtils.parseTimeInSecond(tmpOn);
}
return null;
}
@Override
public List<String> getScopes() {
String tmpScopes = null;
if(TipologiaClaimsNegoziazione.OAUTH2_RFC_6749.equals(this.parser)) {
tmpScopes = TokenUtilities.getClaimAsString(this.claims,ClaimsNegoziazione.OAUTH2_RFC_6749_SCOPE);
}
else if(TipologiaClaimsNegoziazione.MAPPING.equals(this.parser)) {
return readMappingScopes();
}
return readScope(tmpScopes);
}
public List<String> readMappingScopes() {
List<String> claimNames = TokenUtilities.getClaims(this.parserConfig, Costanti.RETRIEVE_TOKEN_PARSER_SCOPE);
List<String> tmpScopesList = TokenUtilities.getFirstClaimAsList(this.claims, claimNames);
List<String> lNull = null;
if(tmpScopesList!=null && !tmpScopesList.isEmpty()) {
return readMappingScopes(tmpScopesList);
}
else {
return lNull;
}
}
public List<String> readMappingScopes(List<String> tmpScopesList) {
List<String> scopes = new ArrayList<>();
for (String s : tmpScopesList) {
List<String> tmp = readScope(s);
if(tmp!=null && !tmp.isEmpty()) {
for (String sTmp : tmp) {
if(!scopes.contains(sTmp)) {
scopes.add(sTmp);
}
}
}
}
return scopes;
}
private List<String> readScope(String tmpScopes) {
List<String> lNull = null;
if(tmpScopes!=null) {
String [] tmpArray = tmpScopes.split(" ");
if(tmpArray!=null && tmpArray.length>0) {
List<String> scopes = new ArrayList<>();
for (int i = 0; i < tmpArray.length; i++) {
scopes.add(tmpArray[i].trim());
}
return scopes;
}
}
return lNull;
}
}