package mujina.idp;
import mujina.api.IdpConfiguration;
import mujina.saml.SAMLAttribute;
import mujina.saml.SAMLPrincipal;
import org.opensaml.common.binding.SAMLMessageContext;
import org.opensaml.saml2.core.AuthnRequest;
import org.opensaml.saml2.core.NameIDType;
import org.opensaml.saml2.metadata.provider.MetadataProviderException;
import org.opensaml.ws.message.decoder.MessageDecodingException;
import org.opensaml.ws.message.encoder.MessageEncodingException;
import org.opensaml.xml.io.MarshallingException;
import org.opensaml.xml.security.SecurityException;
import org.opensaml.xml.signature.SignatureException;
import org.opensaml.xml.validation.ValidationException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import static java.util.Collections.singletonList;
import static java.util.stream.Collectors.toList;
@Controller
public class SsoController {
@Autowired
private SAMLMessageHandler samlMessageHandler;
@Autowired
private IdpConfiguration idpConfiguration;
@GetMapping("/SingleSignOnService")
public void singleSignOnServiceGet(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException, MarshallingException, SignatureException, MessageEncodingException, ValidationException, SecurityException, MessageDecodingException, MetadataProviderException {
doSSO(request, response, authentication, false);
}
@PostMapping("/SingleSignOnService")
public void singleSignOnServicePost(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException, MarshallingException, SignatureException, MessageEncodingException, ValidationException, SecurityException, MessageDecodingException, MetadataProviderException {
doSSO(request, response, authentication, true);
}
private void doSSO(HttpServletRequest request, HttpServletResponse response, Authentication authentication, boolean postRequest) throws ValidationException, SecurityException, MessageDecodingException, MarshallingException, SignatureException, MessageEncodingException, MetadataProviderException {
SAMLMessageContext messageContext = samlMessageHandler.extractSAMLMessageContext(request, response, postRequest);
AuthnRequest authnRequest = (AuthnRequest) messageContext.getInboundSAMLMessage();
String assertionConsumerServiceURL = idpConfiguration.getAcsEndpoint() != null ? idpConfiguration.getAcsEndpoint() : authnRequest.getAssertionConsumerServiceURL();
SAMLPrincipal principal = new SAMLPrincipal(
authentication.getName(),
NameIDType.UNSPECIFIED,
attributes(authentication.getName()),
authnRequest.getIssuer().getValue(),
authnRequest.getID(),
assertionConsumerServiceURL,
messageContext.getRelayState());
samlMessageHandler.sendAuthnResponse(principal, response);
}
private List<SAMLAttribute> attributes(String uid) {
return idpConfiguration.getAttributes().entrySet().stream()
.map(entry -> entry.getKey().equals("urn:mace:dir:attribute-def:uid") ?
new SAMLAttribute(entry.getKey(), singletonList(uid)) :
new SAMLAttribute(entry.getKey(), entry.getValue()))
.collect(toList());
}
}