package org.pac4j.saml.credentials.authenticator;

import org.opensaml.core.xml.XMLObject;
import org.opensaml.saml.saml2.core.Attribute;
import org.opensaml.saml.saml2.core.Conditions;
import org.pac4j.core.context.WebContext;
import org.pac4j.core.credentials.authenticator.Authenticator;
import org.pac4j.core.exception.CredentialsException;
import org.pac4j.core.exception.HttpAction;
import org.pac4j.core.profile.definition.CommonProfileDefinition;
import org.pac4j.core.profile.definition.ProfileDefinitionAware;
import org.pac4j.saml.credentials.SAML2Credentials;
import org.pac4j.saml.profile.SAML2Profile;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.w3c.dom.Element;

import java.util.ArrayList;
import java.util.List;

/**
 * Authenticator for SAML 2.
 *
 * @author Jerome Leleu
 * @since 2.0.0
 */
public class SAML2Authenticator extends ProfileDefinitionAware<SAML2Profile> implements Authenticator<SAML2Credentials> {

    public static final String SAML_CONDITION_NOT_BEFORE_ATTRIBUTE = "notBefore";
    public static final String SAML_CONDITION_NOT_ON_OR_AFTER_ATTRIBUTE = "notOnOrAfter";
    public static final String SESSION_INDEX = "sessionindex";

    protected final Logger logger = LoggerFactory.getLogger(getClass());

    protected void internalInit(final WebContext context) {
        defaultProfileDefinition(new CommonProfileDefinition<>(x -> new SAML2Profile()));
    }

    @Override
    public void validate(final SAML2Credentials credentials, final WebContext context) throws HttpAction, CredentialsException {
        init(context);

        final SAML2Profile profile = getProfileDefinition().newProfile();
        profile.setId(credentials.getNameId().getValue());
        profile.addAttribute(SESSION_INDEX, credentials.getSessionIndex());
        for (final Attribute attribute : credentials.getAttributes()) {
            logger.debug("Processing profile attribute {}", attribute);

            final List<String> values = new ArrayList<>();
            for (final XMLObject attributeValue : attribute.getAttributeValues()) {
                final Element attributeValueElement = attributeValue.getDOM();
                if (attributeValueElement != null) {
                    final String value = attributeValueElement.getTextContent();
                    logger.debug("Adding attribute value {} for attribute {}", value,
                            attribute.getFriendlyName());
                    values.add(value);
                } else {
                    logger.warn("Attribute value DOM element is null for {}", attribute);
                }
            }

            if (!values.isEmpty()) {
                getProfileDefinition().convertAndAdd(profile, attribute.getName(), values);
            } else {
                logger.debug("No attribute values found for {}", attribute.getName());
            }
        }

        // Retrieve conditions attributes
        Conditions conditions = credentials.getConditions();
        if (conditions != null) {
            profile.addAttribute(SAML_CONDITION_NOT_BEFORE_ATTRIBUTE, conditions.getNotBefore());
            profile.addAttribute(SAML_CONDITION_NOT_ON_OR_AFTER_ATTRIBUTE, conditions.getNotOnOrAfter());
        }

        credentials.setUserProfile(profile);
    }
}

@@ -513,16 +513,57 @@
 nAware;%0A
+import org.pac4j.core.util.CommonHelper;%0A
 import o
@@ -820,16 +820,17 @@
  SAML 2.
+0
 %0A *%0A * @
@@ -1976,24 +1976,147 @@
 ttribute);%0A%0A
+            final String name = attribute.getName();%0A            final String friendlyName = attribute.getFriendlyName();%0A%0A
             
@@ -2528,24 +2528,29 @@
 or attribute
+ %7B%7D /
  %7B%7D%22, value,
@@ -2578,30 +2578,23 @@
         
-attribute.getF
+name, f
 riendlyN
@@ -2592,26 +2592,24 @@
 friendlyName
-()
 );%0A         
@@ -2885,35 +2885,170 @@
 rofile, 
-attribute.get
+name, values);%0A                if (CommonHelper.isNotBlank(friendlyName)) %7B%0A                    getProfileDefinition().convertAndAdd(profile, friendly
 Name
-()
 , values
@@ -3042,32 +3042,50 @@
 yName, values);%0A
+                %7D%0A
             %7D el
@@ -3154,35 +3154,20 @@
 or %7B%7D%22, 
-attribute.getN
+n
 ame
-()
 );%0A     

Use friendly names for the SAML2Profile (#832)