001/*
002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003 *
004 * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved
005 *
006 * The contents of this file are subject to the terms
007 * of the Common Development and Distribution License
008 * (the License). You may not use this file except in
009 * compliance with the License.
010 *
011 * You can obtain a copy of the License at
012 * https://opensso.dev.java.net/public/CDDLv1.0.html or
013 * opensso/legal/CDDLv1.0.txt
014 * See the License for the specific language governing
015 * permission and limitations under the License.
016 *
017 * When distributing Covered Code, include this CDDL
018 * Header Notice in each file and include the License file
019 * at opensso/legal/CDDLv1.0.txt.
020 * If applicable, add the following below the CDDL Header,
021 * with the fields enclosed by brackets [] replaced by
022 * your own identifying information:
023 * "Portions Copyrighted [year] [name of copyright owner]"
024 *
025 * $Id: FSAuthnRequest.java,v 1.4 2008/07/08 06:03:37 exu Exp $
026 *
027 * Portions Copyrighted 2014-2016 ForgeRock AS.
028 */
029
030package com.sun.identity.federation.message;
031
032import static org.forgerock.http.util.Uris.urlEncodeQueryParameterNameOrValue;
033import static org.forgerock.openam.utils.Time.*;
034
035import com.sun.identity.federation.common.FSUtils;
036import com.sun.identity.federation.common.IFSConstants;
037import com.sun.identity.federation.message.common.Extension;
038import com.sun.identity.federation.message.common.FSMsgException;
039import com.sun.identity.federation.message.common.RequestAuthnContext;
040import com.sun.identity.saml.common.SAMLConstants;
041import com.sun.identity.saml.common.SAMLException;
042import com.sun.identity.saml.common.SAMLResponderException;
043import com.sun.identity.saml.common.SAMLUtils;
044import com.sun.identity.saml.protocol.AbstractRequest;
045import com.sun.identity.saml.xmlsig.XMLSignatureManager;
046import com.sun.identity.shared.DateUtils;
047import com.sun.identity.shared.encode.Base64;
048import com.sun.identity.shared.xml.XMLUtils;
049import java.text.ParseException;
050import java.util.ArrayList;
051import java.util.Collections;
052import java.util.Date;
053import java.util.Iterator;
054import java.util.List;
055import javax.servlet.http.HttpServletRequest;
056import org.w3c.dom.Document;
057import org.w3c.dom.Element;
058import org.w3c.dom.Node;
059import org.w3c.dom.NodeList;
060
061/**
062 * The class <code>FSAuthnRequest</code> is used to create , parse
063 * <code>AuthnRequest</code> object.
064 *
065 * @supported.all.api
066 * @deprecated since 12.0.0
067 */
068@Deprecated
069public class FSAuthnRequest extends AbstractRequest {
070    private List extensions = null;
071    private boolean isPassive = false;
072    private boolean forceAuthn = false;
073    private boolean federate = false;
074    private String nameIDPolicy = null;
075    private String protocolProfile = null;
076    private String providerId = null;
077    private RequestAuthnContext authnContext = null;
078    private String relayState = null;
079    protected String xmlString = null;
080    protected String signatureString = null;
081    protected String authContextCompType = null;
082    protected String id = null;
083    protected String assertionConsumerServiceID = null;
084    protected String consentURI = null;
085    protected String affiliationID = null;
086    protected int minorVersion = 0;
087    protected FSScoping scoping = null;
088    private static final String QUERY_STRING_EXTENSION_PREFIX = "AE_";    
089    /**
090     * Default AuthnRequest construtor
091     */
092    public FSAuthnRequest() {
093        setIssueInstant(newDate());
094    }
095    
096    /**
097     * Constructor to create <code>FSAuthnRequest</code> object.
098     *
099     * @param requestId the request identifier.
100     * @param respondWiths List of respond withs attributes.
101     * @param providerID provider id of the requesting provider.
102     * @param forceAuthn Force Authentication boolean value.
103     * @param isPassive attribute for IDP to be passive or active.
104     * @param fed attribute to distingush this request for Federation or SSO
105     * @param nameIDPolicy Name ID Policy for this request, possible values
106     *                     are "none", "onetime", "federated", "any".
107     * @param protocolProf ProtocolProfile used for the SSO.
108     * @param authnCxt Authentication Context used for the SSO.
109     * @param relaySt Relay State i.e. original URL to be redirected after SSO.
110     * @param authContextCompType AuthContext comparison type.
111     * @throws <code>FSMsgException</code> on error.
112     */
113    public FSAuthnRequest(String requestId,
114            List respondWiths,
115            String providerID,
116            boolean forceAuthn,
117            boolean isPassive,
118            boolean fed,
119            String nameIDPolicy,
120            String protocolProf,
121            RequestAuthnContext authnCxt,
122            String relaySt,
123            String authContextCompType)
124            throws FSMsgException {
125        
126        setIssueInstant(newDate());
127        if((respondWiths != null) && (respondWiths != Collections.EMPTY_LIST)) {
128            int length = respondWiths.size();
129            for(int i = 0; i < length; i++) {
130                Object temp = respondWiths.get(i);
131                if(!(temp instanceof String)) {
132                    FSUtils.debug.error("FSAuthnRequest: wrong input for " +
133                            "RespondWith");
134                    throw new FSMsgException("wrongInput", null);
135                }
136            }
137            this.respondWiths = respondWiths;
138        }
139        
140        if ((requestId != null) && (requestId.length() != 0)) {
141            requestID = requestId;
142        } else {
143            // random generate one
144            requestID = SAMLUtils.generateID();
145            if (requestID == null) {
146                FSUtils.debug.error("FSAuthnRequest: couldn't gen RequestID.");
147                throw new FSMsgException("errorGenerateID",null);
148            }
149        }
150        this.isPassive = isPassive;
151        this.forceAuthn = forceAuthn;
152        this.providerId = providerID;
153        this.federate = fed;
154        this.nameIDPolicy = nameIDPolicy;
155        this.protocolProfile = protocolProf;
156        this.relayState = relaySt;
157        this.authnContext = authnCxt;
158        this.authContextCompType = authContextCompType;
159        id = requestID;
160    }
161    
162    /**
163     * Constructor to create <code>FSAuthnRequest</code> object.
164     *
165     * @param root the Document Element object.
166     * @throws <code>FSMsgException</code> on error.
167     */
168    public FSAuthnRequest(Element root) throws FSMsgException {
169        String tag = null;
170        if (root == null) {
171            FSUtils.debug.error("FSAuthnRequest(Element): null input.");
172            throw new FSMsgException("nullInput",null);
173        }
174        if(((tag = root.getLocalName()) == null) ||
175                (!tag.equals(IFSConstants.AUTHN_REQUEST))) {
176            FSUtils.debug.error("FSAuthnRequest(Element): wrong input");
177            throw new FSMsgException("wrongInput",null);
178        }
179        // Attribute IssueInstant
180        String instantString = root.getAttribute(IFSConstants.ISSUE_INSTANT);
181        if ((instantString == null) || (instantString.length() == 0)) {
182            FSUtils.debug.error("FSAuthnRequest(Element): " 
183                                 + "missing IssueInstant");
184            String[] args = { IFSConstants.ISSUE_INSTANT };
185            throw new FSMsgException("missingAttribute",args);
186        } else {
187            try {
188                issueInstant = DateUtils.stringToDate(instantString);
189            } catch (ParseException e) {
190                FSUtils.debug.error("FSAuthnRequest(Element): "
191                 + "could not parse IssueInstant", e);
192                throw new FSMsgException("wrongInput", null);
193            }
194        }
195        // Consent attribute
196        consentURI = root.getAttribute(IFSConstants.CONSENT);
197        
198        id = root.getAttribute(IFSConstants.ID);
199        requestID = root.getAttribute(IFSConstants.AUTH_REQUEST_ID);
200        parseMajorVersion(root.getAttribute(IFSConstants.MAJOR_VERSION));
201        parseMinorVersion(root.getAttribute(IFSConstants.MINOR_VERSION));
202        NodeList contentnl = root.getChildNodes();
203        Node child;
204        String nodeName;
205        int length = contentnl.getLength();
206        for(int i = 0; i < length; i++) {
207            child = contentnl.item(i);
208            if ((nodeName = child.getLocalName()) != null) {
209                if (nodeName.equals(IFSConstants.RESPONDWITH)) {
210                    if (respondWiths == Collections.EMPTY_LIST) {
211                        respondWiths = new ArrayList();
212                    }
213                    respondWiths.add(XMLUtils.getElementValue((Element) child));
214                } else if (nodeName.equals(IFSConstants.PROVIDER_ID)) {
215                    if(providerId != null && providerId.length() != 0) {
216                        FSUtils.debug.error("FSAuthnRequest(Element): should"
217                                + "contain only one ProviderID.");
218                        throw new FSMsgException("wrongInput",null);
219                    }
220                    providerId = XMLUtils.getElementValue((Element) child);
221                } else if(nodeName.equals(IFSConstants.NAMEID_POLICY_ELEMENT)) {
222                    nameIDPolicy=XMLUtils.getElementValue((Element) child);
223                    
224                    if (nameIDPolicy != null &&
225                            (nameIDPolicy.equals(
226                            IFSConstants.NAME_ID_POLICY_FEDERATED) ||
227                            nameIDPolicy.equals(
228                            IFSConstants.NAME_ID_POLICY_ONETIME))
229                            ) {
230                        federate = true;
231                    }
232                } else if (nodeName.equals(IFSConstants.FEDERATE)) {
233                    String strFederate = 
234                             XMLUtils.getElementValue((Element)child);
235                    if(strFederate != null && strFederate.length() != 0 &&
236                            strFederate.equals(IFSConstants.TRUE)
237                                    || strFederate.equals(IFSConstants.ONE)) {
238                        federate = true;
239                    }
240                } else if (nodeName.equals(IFSConstants.IS_PASSIVE_ELEM)) {
241                    String strIsPassive =
242                            XMLUtils.getElementValue((Element) child);
243                    if(strIsPassive != null && strIsPassive.length() != 0 &&
244                            strIsPassive.equals(IFSConstants.TRUE)) {
245                        isPassive = true;
246                    } else {
247                        isPassive = false;
248                    }
249                } else if (nodeName.equals(IFSConstants.FORCE_AUTHN_ELEM)) {
250                    String strForceAuthn =
251                            XMLUtils.getElementValue((Element) child);
252                    if(strForceAuthn != null && strForceAuthn.length() != 0 &&
253                            strForceAuthn.equals(IFSConstants.TRUE)) {
254                        forceAuthn = true;
255                    } else {
256                        forceAuthn = false;
257                    }
258                } else if (nodeName.equals(IFSConstants.PROTOCOL_PROFILE)) {
259                    if(protocolProfile != null 
260                            && protocolProfile.length() != 0) {
261                        FSUtils.debug.error("FSAuthnRequest(Element): "
262                                + "should contain only one ProtocolProfile.");
263                        throw new FSMsgException("wrongInput",null);
264                    }
265                    protocolProfile = XMLUtils.getElementValue((Element) child);
266                    
267                } else if (nodeName.equals(IFSConstants.AUTHN_CONTEXT)) {
268                    authnContext = new RequestAuthnContext((Element) child);
269                    
270                } else if (nodeName.equals(
271                                   IFSConstants.REQUEST_AUTHN_CONTEXT)) {
272                    authnContext = new RequestAuthnContext((Element) child);
273                    
274                } else if (nodeName.equals(IFSConstants.RELAY_STATE)) {
275                    relayState = XMLUtils.getElementValue((Element) child);
276                    
277                } else if (nodeName.equals(
278                                 IFSConstants.AUTHN_CONTEXT_COMPARISON)) {
279                    authContextCompType =
280                            XMLUtils.getElementValue((Element) child);
281                    if(!(authContextCompType.equals(IFSConstants.MINIMUM) ||
282                            authContextCompType.equals(IFSConstants.EXACT) ||
283                            authContextCompType.equals(IFSConstants.MAXIMUM) ||
284                            authContextCompType.equals(IFSConstants.BETTER)) ) {
285                        throw new FSMsgException("wrongInput",null);
286                    }
287                } else if (nodeName.equals(
288                             IFSConstants.ASSERTION_CONSUMER_SVC_ID)) {
289                    assertionConsumerServiceID =
290                            XMLUtils.getElementValue((Element) child);
291                } else if(nodeName.equals(IFSConstants.AFFILIATIONID)) {
292                    affiliationID = XMLUtils.getElementValue((Element) child);
293                } else if(nodeName.equals(IFSConstants.EXTENSION)) {
294                    if (extensions == null) {
295                        extensions = new ArrayList();
296                    }
297                    extensions.add(new Extension((Element)child));
298                } else if(nodeName.equals(IFSConstants.SCOPING)) {
299                    scoping = new FSScoping((Element)child);
300                } else {
301                    FSUtils.debug.error("FSAuthnRequest(Element): invalid"
302                            + " node" + nodeName);
303                    throw new FSMsgException("wrongInput",null);
304                }
305            }
306        }
307        
308        //check for signature
309        List signs = XMLUtils.getElementsByTagNameNS1(root,
310                SAMLConstants.XMLSIG_NAMESPACE_URI,
311                SAMLConstants.XMLSIG_ELEMENT_NAME);
312        int signsSize = signs.size();
313        if (signsSize == 1) {
314            Element elem = (Element)signs.get(0);
315            setSignature(elem);
316            xmlString = XMLUtils.print(root);
317            signed = true;
318        } else if (signsSize != 0) {
319            FSUtils.debug.error("FSAuthnRequest(Element): "
320                    + "included more than one Signature element.");
321            throw new FSMsgException("moreElement",null);
322        }
323        //end check for signature
324    }
325    
326    /**
327     * This method translates the request to an XML document String based on
328     * the Request schema described above.
329     * NOTE: this is a complete AuthnRequest xml string with RequestID,
330     * MajorVersion, etc.
331     *
332     * @return XML String representing the request.
333     * @throws FSMsgException if there is an error.
334     */
335    public String toXMLString() throws FSMsgException {
336        return toXMLString(true, true);
337    }
338    
339    /**
340     * Creates a String representation of the &lt;lib:AuthnRequest&gt; element.
341     *
342     * @param includeNS : Determines whether or not the namespace qualifier
343     *          is prepended to the Element when converted
344     * @param declareNS : Determines whether or not the namespace is declared
345     *          within the Element.
346     * @return string containing the valid XML for this element.
347     * @throws FSMsgException if there is an error.
348     */
349    public String toXMLString(
350            boolean includeNS, boolean declareNS
351            ) throws FSMsgException {
352        return toXMLString(includeNS, declareNS, false);
353    }
354    
355    /**
356     * Creates a String representation of the &lt;lib:AuthnRequest&gt; element.
357     *
358     * @param includeNS  Determines whether or not the namespace qualifier
359     *          is prepended to the Element when converted
360     * @param declareNS Determines whether or not the namespace is declared
361     *          within the Element.
362     * @param includeHeader Determines whether the output include the xml
363     *        declaration header.
364     * @return A string containing the valid XML for this element.
365     * @throws FSMsgException if there is an error.
366     */
367    public String toXMLString(boolean includeNS,
368            boolean declareNS,
369            boolean includeHeader) throws FSMsgException {
370        if (xmlString != null) {
371            return xmlString;
372        }
373        if((providerId == null) || (providerId.length() == 0)){
374            FSUtils.debug.error("FSAuthnRequest.toXMLString: "
375                    + "providerId is null in the request with requestId:"
376                    + requestID);
377            String[] args = { requestID };
378            throw new FSMsgException("nullProviderIdWRequestId",args);
379        }
380        if ((requestID == null) || (requestID.length() == 0)){
381            requestID = SAMLUtils.generateID();
382            if (requestID == null) {
383                FSUtils.debug.error("FSAuthnRequest.toXMLString: "
384                        + "couldn't generate RequestID.");
385                throw new FSMsgException("errorGenerateID",null);
386            }
387        }
388        
389        StringBuffer xml = new StringBuffer(300);
390        if (includeHeader) {
391            xml.append("<?xml version=\"1.0\" encoding=\"").
392                    append(IFSConstants.DEFAULT_ENCODING).append("\" ?>");
393        }
394        String prefix = "";
395        String samlpPrefix = "";
396        String uri = "";
397        String samlpUri = "";
398        if (includeNS) {
399            prefix = IFSConstants.LIB_PREFIX;
400            samlpPrefix = IFSConstants.PROTOCOL_PREFIX;
401        }
402        if (declareNS) {
403            if(minorVersion ==  IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) {
404                uri = IFSConstants.LIB_12_NAMESPACE_STRING;
405            } else {
406                uri = IFSConstants.LIB_NAMESPACE_STRING;
407            }
408            samlpUri = IFSConstants.PROTOCOL_NAMESPACE_STRING;
409        }
410        
411        String instantString = DateUtils.toUTCDateFormat(issueInstant);
412        
413        if (requestID != null) {
414            xml.append(IFSConstants.LEFT_ANGLE)
415               .append(prefix)
416               .append(IFSConstants.AUTHN_REQUEST)
417               .append(uri)
418               .append(IFSConstants.SPACE)
419               .append(samlpUri);
420 
421            if (minorVersion == IFSConstants.FF_11_PROTOCOL_MINOR_VERSION &&
422                    id != null && !(id.length() == 0)){
423                xml.append(IFSConstants.SPACE)
424                   .append(IFSConstants.ID)
425                   .append(IFSConstants.EQUAL_TO)
426                   .append(IFSConstants.QUOTE)
427                   .append(id)
428                   .append(IFSConstants.QUOTE);
429            }
430            xml.append(IFSConstants.SPACE)
431               .append(IFSConstants.REQUEST_ID)
432               .append(IFSConstants.EQUAL_TO)
433               .append(IFSConstants.QUOTE)
434               .append(requestID)
435               .append(IFSConstants.QUOTE)
436               .append(IFSConstants.SPACE)
437               .append(IFSConstants.MAJOR_VERSION)
438               .append(IFSConstants.EQUAL_TO)
439               .append(IFSConstants.QUOTE)
440               .append(majorVersion)
441               .append(IFSConstants.QUOTE)
442               .append(IFSConstants.SPACE)
443               .append(IFSConstants.MINOR_VERSION)
444               .append(IFSConstants.EQUAL_TO)
445               .append(IFSConstants.QUOTE)
446               .append(minorVersion)
447               .append(IFSConstants.QUOTE)
448               .append(IFSConstants.SPACE)
449               .append(IFSConstants.ISSUE_INSTANT)
450               .append(IFSConstants.EQUAL_TO)
451               .append(IFSConstants.QUOTE)
452               .append(instantString)
453               .append(IFSConstants.QUOTE);
454
455            if (consentURI != null) {
456                xml.append(IFSConstants.SPACE) 
457                   .append(IFSConstants.CONSENT)
458                   .append(IFSConstants.EQUAL_TO)
459                   .append(IFSConstants.QUOTE)
460                   .append(consentURI)
461                   .append(IFSConstants.QUOTE);
462            }
463            xml.append(IFSConstants.RIGHT_ANGLE);
464            
465            if((respondWiths != null) &&
466                    (respondWiths != Collections.EMPTY_LIST)) {
467                Iterator i = respondWiths.iterator();
468                while (i.hasNext()) {
469                    xml.append(IFSConstants.LEFT_ANGLE)
470                       .append(samlpPrefix)
471                       .append(IFSConstants.RESPONDWITH)
472                       .append(IFSConstants.RIGHT_ANGLE)
473                       .append((String) i.next())
474                       .append(IFSConstants.START_END_ELEMENT)
475                       .append(samlpPrefix)
476                       .append(IFSConstants.RESPONDWITH)
477                       .append(IFSConstants.RIGHT_ANGLE);
478                }
479            }
480            
481            if (signed) {
482                if (signatureString != null) {
483                    xml.append(signatureString);
484                } else if (signature != null) {
485                    signatureString = XMLUtils.print(signature);
486                    xml.append(signatureString);
487                }
488            }
489
490            if ((extensions != null) && (!extensions.isEmpty())) {
491                for(Iterator iter = extensions.iterator(); iter.hasNext();) {
492                    Extension extension = (Extension)iter.next();
493                    extension.setMinorVersion(minorVersion);
494                    xml.append(extension.toXMLString());
495                }
496
497            }
498
499            xml.append(IFSConstants.LEFT_ANGLE)
500               .append(prefix)
501               .append(IFSConstants.PROVIDER_ID)
502               .append(IFSConstants.RIGHT_ANGLE)
503               .append(providerId)
504               .append(IFSConstants.START_END_ELEMENT)
505               .append(prefix)
506               .append(IFSConstants.PROVIDER_ID)
507               .append(IFSConstants.RIGHT_ANGLE);
508            
509            if (affiliationID != null) {
510                xml.append(IFSConstants.LEFT_ANGLE)
511                   .append(prefix)
512                   .append(IFSConstants.AFFILIATIONID)
513                   .append(IFSConstants.RIGHT_ANGLE)
514                   .append(affiliationID)
515                   .append(IFSConstants.START_END_ELEMENT)
516                   .append(prefix)
517                   .append(IFSConstants.AFFILIATIONID)
518                   .append(IFSConstants.RIGHT_ANGLE);
519            }
520            
521            if (minorVersion == IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) {
522                String strFederate = IFSConstants.NAME_ID_POLICY_NONE;
523                if (federate) {
524                    strFederate = IFSConstants.NAME_ID_POLICY_FEDERATED;
525                    if (nameIDPolicy != null && nameIDPolicy.length()>0) {
526                        strFederate = nameIDPolicy;
527                    }
528                }
529                xml.append(IFSConstants.LEFT_ANGLE)
530                   .append(prefix)
531                   .append(IFSConstants.NAMEID_POLICY_ELEMENT)
532                   .append(IFSConstants.RIGHT_ANGLE)
533                   .append(strFederate)
534                   .append(IFSConstants.START_END_ELEMENT)
535                   .append(prefix)
536                   .append(IFSConstants.NAMEID_POLICY_ELEMENT)
537                   .append(IFSConstants.RIGHT_ANGLE);
538            } else {
539                String strFederate = IFSConstants.FALSE;
540                if (federate) {
541                    strFederate = IFSConstants.TRUE;
542                }
543                xml.append(IFSConstants.LEFT_ANGLE)
544                   .append(prefix)
545                   .append(IFSConstants.FEDERATE)
546                   .append(IFSConstants.RIGHT_ANGLE)
547                   .append(strFederate)
548                   .append(IFSConstants.START_END_ELEMENT)
549                   .append(prefix)
550                   .append(IFSConstants.FEDERATE)
551                   .append(IFSConstants.RIGHT_ANGLE);
552            }
553            
554            String strForceAuthn = IFSConstants.FALSE;
555            if (forceAuthn) {
556                strForceAuthn = IFSConstants.TRUE;
557            }
558            
559            xml.append(IFSConstants.LEFT_ANGLE)
560               .append(prefix)
561               .append(IFSConstants.FORCE_AUTHN_ELEM)
562               .append(IFSConstants.RIGHT_ANGLE)
563               .append(strForceAuthn)
564               .append(IFSConstants.START_END_ELEMENT)
565               .append(prefix)
566               .append(IFSConstants.FORCE_AUTHN_ELEM)
567               .append(IFSConstants.RIGHT_ANGLE);
568            
569            String strIsPassive = IFSConstants.FALSE;
570            if (isPassive) {
571                strIsPassive = IFSConstants.TRUE;
572            }
573            
574            xml.append(IFSConstants.LEFT_ANGLE)
575               .append(prefix)
576               .append(IFSConstants.IS_PASSIVE_ELEM)
577               .append(IFSConstants.RIGHT_ANGLE)
578               .append(strIsPassive)
579               .append(IFSConstants.START_END_ELEMENT)
580               .append(prefix)
581               .append(IFSConstants.IS_PASSIVE_ELEM)
582               .append(IFSConstants.RIGHT_ANGLE);
583            
584            if(protocolProfile != null && protocolProfile.length() != 0) {
585                xml.append(IFSConstants.LEFT_ANGLE)
586                   .append(prefix)
587                   .append(IFSConstants.PROTOCOL_PROFILE)
588                   .append(IFSConstants.RIGHT_ANGLE)
589                   .append(protocolProfile)
590                   .append(IFSConstants.START_END_ELEMENT)
591                   .append(prefix)
592                   .append(IFSConstants.PROTOCOL_PROFILE)
593                   .append(IFSConstants.RIGHT_ANGLE);
594            }
595            
596            if(assertionConsumerServiceID != null) {
597                xml.append(IFSConstants.LEFT_ANGLE)
598                   .append(prefix)
599                   .append(IFSConstants.ASSERTION_CONSUMER_SVC_ID)
600                   .append(IFSConstants.RIGHT_ANGLE)
601                   .append(assertionConsumerServiceID)
602                   .append(IFSConstants.START_END_ELEMENT)
603                   .append(prefix)
604                   .append(IFSConstants.ASSERTION_CONSUMER_SVC_ID)
605                   .append(IFSConstants.RIGHT_ANGLE);
606            }
607            
608            if(authnContext != null){
609                authnContext.setMinorVersion(minorVersion);
610                xml.append(authnContext.toXMLString());
611            }
612            
613            if(relayState != null && relayState.length() != 0){
614                xml.append(IFSConstants.LEFT_ANGLE)
615                   .append(prefix)
616                   .append(IFSConstants.RELAY_STATE)
617                   .append(IFSConstants.RIGHT_ANGLE)
618                   .append(XMLUtils.escapeSpecialCharacters(relayState))
619                   .append(IFSConstants.START_END_ELEMENT)
620                   .append(prefix)
621                   .append(IFSConstants.RELAY_STATE)
622                   .append(IFSConstants.RIGHT_ANGLE);
623            }
624            
625            if (minorVersion == IFSConstants.FF_12_PROTOCOL_MINOR_VERSION)  {
626                if (scoping != null) {
627                    xml.append(scoping.toXMLString(true, false));
628                }
629            }
630            
631            if(minorVersion == IFSConstants.FF_11_PROTOCOL_MINOR_VERSION) {
632                if(authContextCompType != null &&
633                        authContextCompType.length() != 0) {
634                    xml.append(IFSConstants.LEFT_ANGLE)
635                       .append(prefix)
636                       .append(IFSConstants.AUTHN_CONTEXT_COMPARISON)
637                       .append(IFSConstants.RIGHT_ANGLE)
638                       .append(authContextCompType)
639                       .append(IFSConstants.START_END_ELEMENT)
640                       .append(prefix)
641                       .append(IFSConstants.AUTHN_CONTEXT_COMPARISON)
642                       .append(IFSConstants.RIGHT_ANGLE);
643                }
644            }
645            
646            xml.append(IFSConstants.START_END_ELEMENT)
647               .append(prefix)
648               .append(IFSConstants.AUTHN_REQUEST)
649               .append(IFSConstants.RIGHT_ANGLE);
650        } else{
651            FSUtils.debug.error("FSAuthnRequest.toString: requestID is null ");
652            throw new FSMsgException("nullAuthnRequestID",null);
653        }
654        return xml.toString();
655    }
656    
657    /**
658     * Returns the <code>FSAuthnRequest</code> object.
659     *
660     * @param xml the XML string.
661     * @return <code>FSAuthnRequest</code> object.
662     * @throws FSMsgException if there is 
663     *         error creating the object.
664     */
665    public static FSAuthnRequest parseXML(String xml) throws FSMsgException {
666        Document doc = XMLUtils.toDOMDocument(xml, FSUtils.debug);
667        if (doc == null) {
668            FSUtils.debug.error("FSAuthnRequest.parseXML:Error "
669                    + "while parsing input xml string");
670            throw new FSMsgException("parseError",null);
671        }
672        Element root = doc.getDocumentElement();
673        return new FSAuthnRequest(root);
674    }
675    
676    /**
677     * Returns Signed XML String representation of this object.
678     *
679     * @return signed XML String.
680     */
681    public String getSignedXMLString(){
682        return xmlString;
683    }
684    
685    /**
686     * Returns the signature string.
687     *
688     * @return the signature string.
689     */
690    public String getSignatureString(){
691        return signatureString;
692    }
693    
694    /**
695     * Returns a list of <code>Extension</code> objects.
696     * Each entry of the list is a <code>Extension</code> object.
697     *
698     * @return a list of <code>Extension</code> elements.
699     * @see #setExtensions(List)
700     */
701    
702    public List getExtensions() {
703        return extensions;
704    }
705    
706    /**
707     * Sets <code>Extension</code> objects.
708     * Each entry of the list is a <code>Extension</code> object.
709     *
710     * @param extensions a list of <code>Extension</code> objects.
711     * @see #getExtensions
712     */
713    public void setExtensions(List extensions) {
714        this.extensions = extensions;
715    }
716
717    /**
718     * Returns the value of Force Authentication attribute.
719     *
720     * @return the value of Force Authentication attribute.
721     */
722    public boolean getForceAuthn() {
723        return forceAuthn;
724    }
725    
726    /**
727     * Sets the value of Force Authentication attribute.
728     *
729     * @param forceAuthn value of Force Authentication attribute.
730     */
731    public void setForceAuthn(boolean forceAuthn) {
732        this.forceAuthn = forceAuthn;
733    }
734    
735    /**
736     * Returns the value of the <code>isPassive</code> attribute.
737     *
738     * @return value of <code>isPassive</code> attribute.
739     */
740    public boolean getIsPassive() {
741        return isPassive;
742    }
743    
744    /**
745     * Sets the value of the <code>IsPassive</code> attribute.
746     *
747     * @param isPassive value of <code>isPassive</code> attribute.
748     */
749    public void setIsPassive(boolean isPassive) {
750        this.isPassive = isPassive;
751    }
752    
753    /**
754     * Returns the value of the <code>Federate</code> attribute.
755     *
756     * @return the value fo the <code>Federate</code> attribute.
757     */
758    public boolean getFederate() {
759        return federate;
760    }
761    
762    /**
763     * Sets the value of the <code>Federate</code> attribute.
764     *
765     * @param fed the value of the <code>Federate</code> attribute.
766     */
767    public void setFederate(boolean fed) {
768        federate = fed;
769    }
770    
771    /**
772     * Returns the <code>NameIDPolicy</code> object.
773     *
774     * @return the <code>NameIDPolicy</code> object.
775     * @see #setNameIDPolicy(String)
776     */
777    
778    public String getNameIDPolicy() {
779        return nameIDPolicy;
780    }
781    
782    /**
783     * Sets the <code>NameIDPolicy</code> object.
784     *
785     * @param nameIDPolicy the new <code>NameIDPolicy</code> object.
786     * @see #getNameIDPolicy
787     */
788    public void setNameIDPolicy(String nameIDPolicy) {
789        this.nameIDPolicy = nameIDPolicy;
790    }
791    
792    /**
793     * Returns the value of <code>ProtocolProfile<code> attribute.
794     *
795     * @return the value of <code>ProtocolProfile<code> attribute.
796     * @see #setProtocolProfile(String)
797     */
798    public String getProtocolProfile() {
799        return protocolProfile;
800    }
801    
802    /**
803     * Sets the value of <code>ProtocolProfile<code> attribute.
804     *
805     * @param protocolProf the value of <code>ProtocolProfile<code> attribute.
806     * @see #getProtocolProfile()
807     */
808    public void setProtocolProfile(String protocolProf) {
809        protocolProfile = protocolProf;
810    }
811    
812    /**
813     * Returns the value of RelayState attribute.
814     *
815     * @return the value of RelayState attribute.
816     * @see #setRelayState(String)
817     */
818    public String getRelayState() {
819        return relayState;
820    }
821    
822    /**
823     * Set the value of RelayState attribute.
824     *
825     * @param relaySt the value of RelayState attribute.
826     * @see #getRelayState()
827     */
828    public void setRelayState(String relaySt) {
829        relayState = relaySt;
830    }
831
832    /**
833     * Returns the <code>RequestedAuthnContext</code> object.
834     *
835     * @return the <code>RequestedAuthnContext</code> object.
836     * @see #setAuthnContext(RequestAuthnContext)
837     */
838    public RequestAuthnContext getAuthnContext() {
839        return authnContext;
840    }
841    
842    /**
843     * Sets the <code>RequestedAuthnContext</code> object.
844     *
845     * @param authnCxt the <code>RequestAuthnContext</code> object.
846     * @see #getAuthnContext()
847     */
848    public void setAuthnContext(RequestAuthnContext authnCxt) {
849        authnContext = authnCxt;
850    }
851    
852    /**
853     * Returns the value of <code>ProviderID</code> attribute.
854     *
855     * @return the value of <code>ProviderID</code> attribute.
856     * @see #setProviderId(String).
857     */
858    public String getProviderId() {
859        return providerId;
860    }
861    
862    /**
863     * Sets the value of <code>ProviderID</code> attribute.
864     *
865     * @param provId the value of <code>ProviderID</code> attribute.
866     * @see #getProviderId()
867     */
868    public void setProviderId(String provId) {
869        providerId = provId;
870    }
871    
872    /**
873     * Returns the value of AuthContext Comparison attribute.
874     *
875     * @return he value of AuthContext Comparison attribute.
876     * @see #setAuthContextCompType(String)
877     */
878    public String getAuthContextCompType() {
879        return authContextCompType;
880    }
881    
882    /**
883     * Sets the value of AuthContext Comparison attribute.
884     *
885     * @param authType he value of AuthContext Comparison attribute.
886     * @see #getAuthContextCompType()
887     */
888    public void setAuthContextCompType(String authType) {
889        authContextCompType = authType;
890    }
891    
892    /**
893     * Returns the value of <code>id</code> attribute.
894     *
895     * @return the value of <code>id</code> attribute.
896     * @see #setID(String)
897     */
898    public String getID() {
899        return id;
900    }
901    
902    /**
903     * Sets the value of <code>id</code> attribute.
904     *
905     * @param id the value of <code>id</code> attribute.
906     * @see #getID()
907     */
908    public void setID(String id) {
909        this.id = id;
910    }
911
912    /**
913     * Returns the value of the <code>MinorVersion</code> attribute.
914     *
915     * @return the value of the <code>MinorVersion</code> attribute.
916     * @see #setMinorVersion(int)
917     */
918    public int getMinorVersion() {
919        return minorVersion;
920    }
921    
922    /**
923     * Sets the value of the <code>MinorVersion</code> attribute.
924     *
925     * @param version the value of the <code>MinorVersion</code> attribute.
926     * @see #getMinorVersion()
927     */
928    public void setMinorVersion(int version) {
929        minorVersion = version;
930    }
931    
932    /**
933     * Returns the Affliation Identifier.
934     *
935     * @return the Affliation Identifier.
936     * @see #setAffiliationID(String)
937     */
938    public String getAffiliationID() {
939        return affiliationID;
940    }
941    
942    /**
943     * Sets the Affiliation Identifier.
944     *
945     * @param affiliationID the Affiliation Identifier.
946     * @see #getAffiliationID()
947     */
948    public void setAffiliationID(String affiliationID) {
949        this.affiliationID = affiliationID;
950    }
951    
952    /**
953     * Returns the Assertion Consumer Service Identifier.
954     *
955     * @return the  Assertion Consumer Service Identifier.
956     * @see #setAssertionConsumerServiceID(String)
957     */
958    public String getAssertionConsumerServiceID() {
959        return assertionConsumerServiceID;
960    }
961    
962    /**
963     * Sets the Assertion Consumer Service Identifier.
964     *
965     * @param assertionConsumerServiceID the Assertion Consumer 
966     *        Service Identifier.
967     * @see #getAssertionConsumerServiceID
968     */
969    public void setAssertionConsumerServiceID(
970                       String assertionConsumerServiceID) {
971        this.assertionConsumerServiceID = assertionConsumerServiceID;
972    }
973    
974    /** 
975     * Returns the value of <code>consent</code> attribute.
976     *
977     * @return the value of <code>consent</code> attribute.
978     * @see #setConsent(String)
979     */
980    public String getConsent() {
981        return consentURI;
982    }
983    
984    /**
985     * Sets the value of <code>consent</code> attribute.
986     *
987     * @param consentURI the value of <code>consent</code> attribute.
988     * @see #getConsent()
989     */
990    public void setConsent(String consentURI) {
991        this.consentURI = consentURI;
992    }
993    
994    /**
995     * Sets the <code>FSScoping</code> object.
996     *
997     * @param scoping the <code>FSScoping</code> object.
998     * @see #getScoping()
999     */
1000    public void setScoping(FSScoping scoping) {
1001        this.scoping = scoping;
1002    }
1003    
1004    /**
1005     * Returns the <code>FSScoping</code> object.
1006     *
1007     * @return the <code>FSScoping</code> object.
1008     * @see #setScoping(FSScoping)
1009     */
1010    public FSScoping getScoping() {
1011        return scoping;
1012    }
1013    
1014    /**
1015     * Validates the the <code>MajorVersion</code> property in the 
1016     * <code>AuthnRequest</code>.
1017     * 
1018     * @param majorVer the value of <code>MajorVersion</code> property
1019     * @throws FSMsgException if the <code>MajoorVersion</code>
1020     *         is null or is invalid.
1021     */
1022    private void parseMajorVersion(String majorVer) throws FSMsgException {
1023        try {
1024            majorVersion = Integer.parseInt(majorVer);
1025        } catch (NumberFormatException e) {
1026            if (FSUtils.debug.messageEnabled()) {
1027                FSUtils.debug.message("FSAuthnRequest(Element): invalid "
1028                        + "MajorVersion", e);
1029            }
1030            throw new FSMsgException("wrongInput",null);
1031        }
1032        
1033        if (majorVersion != IFSConstants.PROTOCOL_MAJOR_VERSION) {
1034            if (majorVersion > IFSConstants.PROTOCOL_MAJOR_VERSION) {
1035                if (FSUtils.debug.messageEnabled()) {
1036                    FSUtils.debug.message("FSAuthnRequest(Element): "
1037                            + "MajorVersion of the AuthnRequest is too high.");
1038                }
1039                throw new FSMsgException("requestVersionTooHigh",null);
1040            } else {
1041                if (FSUtils.debug.messageEnabled()) {
1042                    FSUtils.debug.message("FSAuthnRequest(Element): "
1043                            + "MajorVersion of the AuthnRequest is too low.");
1044                }
1045                throw new FSMsgException("requestVersionTooLow",null);
1046            }
1047        }
1048        
1049    }
1050    /**
1051     * Validates the the <code>MinorVersion</code> property in the 
1052     * <code>AuthnRequest</code>.
1053     * 
1054     * @param minorVer the value of <code>MinorVersion</code> property
1055     * @throws FSMsgException if the <code>MinorVersion</code>
1056     *         is null or is invalid.
1057     */
1058    private void parseMinorVersion(String minorVer) throws FSMsgException {
1059        try {
1060            minorVersion = Integer.parseInt(minorVer);
1061        } catch (NumberFormatException e) {
1062            if (FSUtils.debug.messageEnabled()) {
1063                FSUtils.debug.message("FSAuthnRequest(Element): invalid "
1064                        + "MinorVersion", e);
1065            }
1066            throw new FSMsgException("wrongInput",null);
1067        }
1068        if(minorVersion > IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) {
1069            if (FSUtils.debug.messageEnabled()) {
1070                FSUtils.debug.message("FSAuthnRequest.checkMinorVersion:"+
1071                        " Minor Version of the AuthnRequest is too high.");
1072            }
1073            throw new FSMsgException("requestVersionTooHigh",null);
1074        } else if (minorVersion < IFSConstants.FF_11_PROTOCOL_MINOR_VERSION) {
1075            if (FSUtils.debug.messageEnabled()) {
1076                FSUtils.debug.message("FSAuthnRequest.checkMinorVersion:" +
1077                        " Minor Version of the AuthnRequest is too low.");
1078            }
1079            throw new FSMsgException("requestVersionTooLow",null);
1080        }
1081        
1082    }
1083
1084    /**
1085     * Checks the value of the <code>MajorVersion</code> property
1086     *  in the <code>AuthnRequest</code>.
1087     *
1088     * @param minorVer the value of <code>MajorVersion</code> property
1089     * @return integer value of <code>MajorVersion</code> property
1090     * @throws FSMsgException if the <code>MajorVersion</code>
1091     *         is null or invalid.
1092     */
1093    private static int checkMajorVersion(String majorVer) 
1094                        throws FSMsgException {
1095        int majorVersion;
1096        if (majorVer == null){
1097            throw new FSMsgException("nullMajorVersion",null);
1098        }
1099        try {
1100            majorVersion = Integer.parseInt(majorVer);
1101        } catch (NumberFormatException e) {
1102            if (FSUtils.debug.messageEnabled()) {
1103                FSUtils.debug.message("FSAuthnRequest.checkMajorVersion: "
1104                        + "invalid MajorVersion: " + e.getMessage());
1105            }
1106            throw new FSMsgException("wrongInput",null);
1107        }
1108        
1109        if (majorVersion != SAMLConstants.PROTOCOL_MAJOR_VERSION) {
1110            if (majorVersion > SAMLConstants.PROTOCOL_MAJOR_VERSION) {
1111                if (FSUtils.debug.messageEnabled()) {
1112                    FSUtils.debug.message("FSAuthnRequest.checkMajorVersion: "
1113                            + "MajorVersion of the AuthnRequest is too high"
1114                            + majorVersion);
1115                }
1116                throw new FSMsgException("requestVersionTooHigh",null);
1117            } else {
1118                if (FSUtils.debug.messageEnabled()) {
1119                    FSUtils.debug.message(
1120                            "FSAuthnRequest.checkMajorVersion:MajorVersion of "
1121                            + "the AuthnRequest is too low. " + majorVersion);
1122                }
1123                throw new FSMsgException("requestVersionTooLow",null);
1124            }
1125        }
1126        return majorVersion;
1127    }
1128    
1129    /**
1130     * Checks the value of the <code>MinorVersion</code> property
1131     *  in the <code>AuthnRequest</code>.
1132     *
1133     * @param minorVer the value of <code>MinorVersion</code> property
1134     * @return integer value of <code>MinorVersion</code> property
1135     * @throws FSMsgException if the <code>MinorVersion</code>
1136     *         is null or invalid.
1137     */
1138    private static int checkMinorVersion(String minorVer)
1139    throws FSMsgException {
1140        int minorVersion;
1141        if (minorVer == null){
1142            throw new FSMsgException("nullMinorVersion",null);
1143        }
1144        try {
1145            minorVersion = Integer.parseInt(minorVer);
1146        } catch (NumberFormatException e) {
1147            if (FSUtils.debug.messageEnabled()) {
1148                FSUtils.debug.message("FSAuthnRequest.checkMinorVersion: "
1149                        + "invalid MinorVersion", e);
1150            }
1151            throw new FSMsgException("wrongInput",null);
1152        }
1153        if(minorVersion == IFSConstants.FF_12_PROTOCOL_MINOR_VERSION ||
1154                minorVersion == IFSConstants.FF_11_PROTOCOL_MINOR_VERSION) {
1155            return minorVersion;
1156        }
1157        if(minorVersion > IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) {
1158            if(FSUtils.debug.messageEnabled()) {
1159                FSUtils.debug.message("FSAuthnRequest.checkMinorVersion:"+
1160                        " Minor Version of the AuthnRequest is too high.");
1161            }
1162            throw new FSMsgException("requestVersionTooHigh",null);
1163        } else {
1164            if(FSUtils.debug.messageEnabled()) {
1165                FSUtils.debug.message("FSAuthnRequest.checkMinorVersion:" +
1166                        " Minor Version of the AuthnRequest is too low.");
1167            }
1168            throw new FSMsgException("requestVersionTooLow",null);
1169        }
1170    }
1171    
1172    /**
1173     * Returns an URL Encoded Query String.
1174     *
1175     * @return a url encoded query string.
1176     * @throws FSMsgException if there is an error.
1177     */
1178    public String toURLEncodedQueryString() throws FSMsgException {
1179        if ((providerId == null) || (providerId.length() == 0)) {
1180            FSUtils.debug.error("FSAuthnRequest.toURLEncodedQueryString: "
1181                    + "providerId is null in the request with requestId:"
1182                    + requestID);
1183            String[] args = { requestID }; 
1184            throw new FSMsgException("nullProviderIdWRequestId",args);
1185        }
1186        if ((requestID == null) || (requestID.length() == 0)){
1187            requestID = SAMLUtils.generateID();
1188            if (requestID == null) {
1189                FSUtils.debug.error("FSAuthnRequest.toURLEncodedQueryString: "
1190                        + "couldn't generate RequestID.");
1191                throw new FSMsgException("errorGenerateID",null);
1192            }
1193        }
1194        
1195        StringBuffer urlEncodedAuthnReq = new StringBuffer(300);
1196        
1197        urlEncodedAuthnReq.append(IFSConstants.AUTH_REQUEST_ID)
1198                          .append(IFSConstants.EQUAL_TO)
1199                          .append(urlEncodeQueryParameterNameOrValue(requestID))
1200                          .append(IFSConstants.AMPERSAND)
1201                          .append(IFSConstants.MAJOR_VERSION)
1202                          .append(IFSConstants.EQUAL_TO)
1203                          .append(majorVersion)
1204                          .append(IFSConstants.AMPERSAND)
1205                          .append(IFSConstants.MINOR_VERSION)
1206                          .append(IFSConstants.EQUAL_TO)
1207                          .append(minorVersion)
1208                          .append(IFSConstants.AMPERSAND);
1209        if ((extensions != null) && (!extensions.isEmpty())) {
1210            Extension extension = (Extension)extensions.get(0);
1211            urlEncodedAuthnReq.append(extension.toURLEncodedQueryString(
1212                QUERY_STRING_EXTENSION_PREFIX)).append(IFSConstants.AMPERSAND);
1213
1214            if (extensions.size() > 1) {
1215                if (FSUtils.debug.warningEnabled()) {
1216                    FSUtils.debug.warning(
1217                        "FSAuthnRequest.toURLEncodedQueryString: " +
1218                        "only one Extension element is allowed and extras " +
1219                        " will be removed");
1220                }
1221            }
1222        }
1223
1224        urlEncodedAuthnReq.append(IFSConstants.PROVIDER_ID)
1225                          .append(IFSConstants.EQUAL_TO)
1226                          .append(urlEncodeQueryParameterNameOrValue(providerId))
1227                          .append(IFSConstants.AMPERSAND);
1228
1229        if (consentURI != null) {
1230            urlEncodedAuthnReq.append(IFSConstants.CONSENT)
1231                              .append(IFSConstants.EQUAL_TO)
1232                              .append(urlEncodeQueryParameterNameOrValue(consentURI))
1233                              .append(IFSConstants.AMPERSAND);
1234        }
1235
1236        if(affiliationID != null) {
1237            urlEncodedAuthnReq.append(IFSConstants.AFFILIATIONID)
1238                              .append(IFSConstants.EQUAL_TO)
1239                              .append(urlEncodeQueryParameterNameOrValue(affiliationID))
1240                              .append(IFSConstants.AMPERSAND);
1241        }
1242        
1243        if (issueInstant != null){
1244            urlEncodedAuthnReq.append(IFSConstants.ISSUE_INSTANT)
1245                              .append(IFSConstants.EQUAL_TO)
1246                              .append(urlEncodeQueryParameterNameOrValue(DateUtils.toUTCDateFormat(issueInstant)))
1247                              .append(IFSConstants.AMPERSAND);
1248        } else {
1249            FSUtils.debug.error("FSAuthnRequest.toURLEncodedQueryString: "
1250                    + "issueInstant missing");
1251            String[] args = { IFSConstants.ISSUE_INSTANT };
1252            throw new FSMsgException("missingAttribute",args);
1253        }
1254        
1255        String strForceAuthn = IFSConstants.FALSE;
1256        if (forceAuthn) {
1257            strForceAuthn = IFSConstants.TRUE;
1258        }
1259        
1260        urlEncodedAuthnReq.append(IFSConstants.FORCE_AUTHN_ELEM)
1261                          .append(IFSConstants.EQUAL_TO)
1262                          .append(strForceAuthn)
1263                          .append(IFSConstants.AMPERSAND);
1264        
1265        String strIsPassive =  IFSConstants.FALSE;
1266        if (isPassive) {
1267            strIsPassive = IFSConstants.TRUE;
1268        }
1269   
1270        urlEncodedAuthnReq.append(IFSConstants.IS_PASSIVE_ELEM)
1271                          .append(IFSConstants.EQUAL_TO)
1272                          .append(strIsPassive)
1273                          .append(IFSConstants.AMPERSAND);
1274        
1275        if (minorVersion == IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) {
1276            String strFederate = IFSConstants.NAME_ID_POLICY_NONE;
1277            if (federate) {
1278                strFederate = IFSConstants.NAME_ID_POLICY_FEDERATED;
1279                if (nameIDPolicy != null && nameIDPolicy.length() > 0) {
1280                    strFederate = nameIDPolicy;
1281                }
1282            }
1283            urlEncodedAuthnReq.append(IFSConstants.NAMEID_POLICY_ELEMENT)
1284                              .append(IFSConstants.EQUAL_TO)
1285                              .append(strFederate)
1286                              .append(IFSConstants.AMPERSAND);
1287        } else {
1288            String strFederate = IFSConstants.FALSE;
1289            if (federate) {
1290                strFederate = IFSConstants.TRUE;
1291            }
1292            urlEncodedAuthnReq.append(IFSConstants.FEDERATE)
1293                              .append(IFSConstants.EQUAL_TO)
1294                              .append(strFederate)
1295                              .append(IFSConstants.AMPERSAND);
1296        }
1297        
1298        if (protocolProfile != null && protocolProfile.length() != 0) {
1299            urlEncodedAuthnReq.append(IFSConstants.PROTOCOL_PROFILE)
1300                              .append(IFSConstants.EQUAL_TO)
1301                              .append(urlEncodeQueryParameterNameOrValue(protocolProfile))
1302                              .append(IFSConstants.AMPERSAND);
1303        }
1304        
1305        if (authnContext != null) {
1306            authnContext.setMinorVersion(minorVersion);
1307            urlEncodedAuthnReq.append(authnContext.toURLEncodedQueryString());
1308        }
1309        
1310        if (relayState != null && relayState.length() != 0) {
1311            urlEncodedAuthnReq.append(IFSConstants.RELAY_STATE)
1312                              .append(IFSConstants.EQUAL_TO)
1313                              .append(urlEncodeQueryParameterNameOrValue(relayState))
1314                              .append(IFSConstants.AMPERSAND);
1315        }
1316        
1317        if (scoping != null) {
1318            urlEncodedAuthnReq.append(scoping.toURLEncodedQueryString());
1319        }
1320        
1321        if (minorVersion == IFSConstants.FF_11_PROTOCOL_MINOR_VERSION) {
1322            if (authContextCompType != null 
1323                       && authContextCompType.length() != 0) {
1324                urlEncodedAuthnReq.append(IFSConstants.AUTHN_CONTEXT_COMPARISON)
1325                                  .append(IFSConstants.EQUAL_TO)
1326                                  .append(urlEncodeQueryParameterNameOrValue(authContextCompType))
1327                                  .append(IFSConstants.AMPERSAND);
1328            }
1329        }
1330        
1331        int len = urlEncodedAuthnReq.length() - 1;
1332        if (urlEncodedAuthnReq.charAt(len) == '&') {
1333            urlEncodedAuthnReq = urlEncodedAuthnReq.deleteCharAt(len);
1334        }
1335        
1336        return urlEncodedAuthnReq.toString();
1337    }
1338    
1339    /**
1340     * Returns a Base64 Encoded String.
1341     *
1342     * @return a Base64 Encoded String.
1343     * @throws FSMsgException if there is an error encoding 
1344     *         the string.
1345     */
1346    public String toBASE64EncodedString() throws FSMsgException {
1347        if((providerId == null) || (providerId.length() == 0)){
1348            FSUtils.debug.error("FSAuthnRequest.toBASE64EncodedString: "
1349                    + "providerId is null in the request with requestId:"
1350                    + requestID);
1351            String[] args = { requestID };
1352            throw new FSMsgException("nullProviderIdWRequestId",args);
1353        }
1354        if ((requestID == null) || (requestID.length() == 0)) {
1355            requestID = SAMLUtils.generateID();
1356            if (requestID == null) {
1357                FSUtils.debug.error("FSAuthnRequest.toBASE64EncodedString: "
1358                        + "couldn't generate RequestID.");
1359                throw new FSMsgException("errorGenerateID",null);
1360            }
1361        }
1362        return Base64.encode(this.toXMLString().getBytes());
1363    }
1364    
1365    /**
1366     * Returns <code>FSAuthnRequest</code> object. The
1367     * object is creating by parsing the <code>HttpServletRequest</code>
1368     * object.
1369     *
1370     * @param request the <code>HttpServletRequest</code> object.
1371     * @throws FSMsgException if there is an error
1372     *         creating <code>FSAuthnRequest</code> object.
1373     */
1374    public static FSAuthnRequest parseURLEncodedRequest(
1375                          HttpServletRequest request) throws FSMsgException {
1376        FSAuthnRequest retAuthnRequest = new FSAuthnRequest();
1377        String authReqID = request.getParameter(IFSConstants.AUTH_REQUEST_ID);
1378        if (authReqID == null || authReqID.length() == 0) {
1379            throw new FSMsgException("nullAuthnRequestID",null);
1380        }
1381        retAuthnRequest.requestID = authReqID;
1382        
1383        String instantString = 
1384            request.getParameter(IFSConstants.ISSUE_INSTANT);
1385        if (instantString == null || instantString.length() == 0) {
1386            String[] args = { IFSConstants.ISSUE_INSTANT };
1387            throw new FSMsgException("missingAttribute",args);
1388        }
1389        try{
1390            retAuthnRequest.issueInstant =
1391                    DateUtils.stringToDate(instantString);
1392        } catch (ParseException e){
1393            throw new FSMsgException("parseError",null);
1394        }
1395        
1396        retAuthnRequest.majorVersion =
1397                checkMajorVersion(request.getParameter(
1398                                          IFSConstants.MAJOR_VERSION));
1399        
1400        retAuthnRequest.minorVersion =
1401                checkMinorVersion(request.getParameter(
1402                                          IFSConstants.MINOR_VERSION));
1403        
1404        String providerId = request.getParameter(IFSConstants.PROVIDER_ID);
1405        if (providerId == null || providerId.length() == 0) {
1406            throw new FSMsgException("nullProviderIdInRequest",null);
1407        } else{
1408            FSUtils.debug.message("ProviderID of the sender: " + providerId);
1409            retAuthnRequest.providerId = providerId;
1410        }
1411        
1412        retAuthnRequest.affiliationID = 
1413            request.getParameter(IFSConstants.AFFILIATIONID);
1414        
1415        String forceAuthn = request.getParameter(IFSConstants.FORCE_AUTHN_ELEM);
1416        if ( forceAuthn != null && forceAuthn.length() != 0 
1417             && (forceAuthn.equals(IFSConstants.TRUE) 
1418             || forceAuthn.equals(IFSConstants.ONE))) {
1419            retAuthnRequest.forceAuthn = true;
1420        } else {
1421            retAuthnRequest.forceAuthn = false;
1422        }
1423        
1424        String isPassive = request.getParameter(IFSConstants.IS_PASSIVE_ELEM);
1425        if (isPassive != null && isPassive.length() != 0 &&
1426                (isPassive.equals(IFSConstants.TRUE) ||
1427                isPassive.equals(IFSConstants.ONE))) 
1428        {
1429            retAuthnRequest.isPassive = true;
1430        } else {
1431            retAuthnRequest.isPassive = false;
1432        }
1433
1434        if (retAuthnRequest.minorVersion
1435                == IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) {
1436            String nameIDPolicy = 
1437                request.getParameter(IFSConstants.NAMEID_POLICY_ELEMENT);
1438            
1439            if (nameIDPolicy != null &&
1440                    (nameIDPolicy.equals(
1441                          IFSConstants.NAME_ID_POLICY_FEDERATED) ||
1442                    nameIDPolicy.equals(
1443                          IFSConstants.NAME_ID_POLICY_ONETIME))
1444                    ) {
1445                retAuthnRequest.federate = true;
1446            }
1447            retAuthnRequest.nameIDPolicy = nameIDPolicy;
1448        } else {
1449            String federate = request.getParameter(IFSConstants.FEDERATE);
1450            if (federate != null &&
1451                    federate.length() != 0 &&
1452                    (federate.equals(IFSConstants.TRUE)||
1453                    federate.equals(IFSConstants.ONE))) {
1454                retAuthnRequest.federate = true;
1455            } else {
1456                retAuthnRequest.federate = false;
1457            }
1458        }
1459        
1460        String protocolProfile = 
1461            request.getParameter(IFSConstants.PROTOCOL_PROFILE);
1462        if (protocolProfile != null && protocolProfile.length() != 0) {
1463            retAuthnRequest.protocolProfile = protocolProfile;
1464        }
1465        
1466        String relayState = request.getParameter(IFSConstants.RELAY_STATE);
1467        if(relayState != null && relayState.length() != 0) {
1468            retAuthnRequest.setRelayState(relayState);
1469        }
1470        
1471        String authnContextComparison = 
1472            request.getParameter(IFSConstants.AUTHN_CONTEXT_COMPARISON);
1473        if(authnContextComparison != null && 
1474                          authnContextComparison.length() != 0) {
1475            retAuthnRequest.setAuthContextCompType(authnContextComparison);
1476            String authType = retAuthnRequest.getAuthContextCompType();
1477            if(! (authType.equals(IFSConstants.MINIMUM) ||
1478                    authType.equals(IFSConstants.EXACT) ||
1479                    authType.equals(IFSConstants.MAXIMUM) ||
1480                    authType.equals(IFSConstants.BETTER)) ) {
1481                throw new FSMsgException("wrongInput",null);
1482            }
1483        }
1484        
1485        retAuthnRequest.authnContext =
1486                RequestAuthnContext.parseURLEncodedRequest(
1487                request, retAuthnRequest.getMinorVersion());
1488        
1489        retAuthnRequest.scoping = FSScoping.parseURLEncodedRequest(request);
1490
1491        Extension extension = Extension.parseURLEncodedRequest(request,
1492            QUERY_STRING_EXTENSION_PREFIX, retAuthnRequest.getMinorVersion());
1493        if (extension != null) {
1494            retAuthnRequest.extensions = new ArrayList();
1495            retAuthnRequest.extensions.add(extension);
1496        }
1497
1498        return retAuthnRequest;
1499    }
1500    
1501    /**
1502     * Returns <code>FSAuthnRequest</code> object. The object
1503     * is created by parsing an Base64 encode authentication
1504     * request string.
1505     *
1506     * @param encodedReq the encode string
1507     * @throws FSMsgException if there is an error
1508     *         creating <code>FSAuthnRequest</code> object.
1509     */
1510    public static FSAuthnRequest parseBASE64EncodedString(String encodedReq) 
1511                                     throws FSMsgException {
1512        if (encodedReq != null && encodedReq.length() != 0) {
1513            String decodedAuthnReq = new String(Base64.decode(encodedReq));
1514            if (FSUtils.debug.messageEnabled()) {
1515                FSUtils.debug.message(
1516                    "FSAuthnRequest.parseBASE64EncodedString: "
1517                    + "decoded input string: " + decodedAuthnReq);
1518            }
1519            return parseXML(decodedAuthnReq);
1520        } else{
1521            if (FSUtils.debug.messageEnabled()) {
1522                FSUtils.debug.message(
1523                        "FSAuthnRequest.parseBASE64EncodedString: "
1524                        + "null String passed in as argument.");
1525            }
1526            throw new FSMsgException("nullInput",null);
1527        }
1528    }
1529    
1530    /**
1531     * Signs the Request.
1532     *
1533     * @param certAlias the Certificate Alias.
1534     * @throws XMLSignatureException if <code>FSAuthnRequest</code>
1535     *         cannot be signed.
1536     */
1537
1538    public void signXML(String certAlias) throws SAMLException {
1539        FSUtils.debug.message("FSAuthnRequest.signXML: Called");
1540        if (signed) {
1541            if (FSUtils.debug.messageEnabled()) {
1542                FSUtils.debug.message("FSAuthnRequest.signXML: "
1543                        + "the assertion is "
1544                        + "already signed.");
1545            }
1546            throw new SAMLResponderException(FSUtils.BUNDLE_NAME,
1547                    "alreadySigned",null);
1548        }
1549        if (certAlias == null || certAlias.length() == 0) {
1550            throw new SAMLResponderException(
1551                    FSUtils.BUNDLE_NAME,"cannotFindCertAlias",null);
1552        }
1553        try{
1554            XMLSignatureManager manager = XMLSignatureManager.getInstance();
1555            if (minorVersion == IFSConstants.FF_11_PROTOCOL_MINOR_VERSION) {
1556                signatureString = manager.signXML(this.toXMLString(true, true),
1557                        certAlias, (String) null, IFSConstants.ID,
1558                        this.id, false);
1559            } else if(minorVersion == 
1560                            IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) {
1561                signatureString = 
1562                        manager.signXML(this.toXMLString(true, true),
1563                        certAlias, (String) null, IFSConstants.REQUEST_ID,
1564                        this.getRequestID(), false);
1565            } else {
1566                if (FSUtils.debug.messageEnabled()) {
1567                    FSUtils.debug.message("invalid minor version.");
1568                }
1569            }
1570            
1571            signature =
1572                    XMLUtils.toDOMDocument(signatureString, FSUtils.debug)
1573                    .getDocumentElement();
1574            
1575            signed = true;
1576            xmlString = this.toXMLString(true, true);
1577        } catch(Exception e){
1578            throw new SAMLResponderException(
1579                            FSUtils.BUNDLE_NAME,"signFailed",null);
1580        }
1581    }
1582    
1583    /**
1584     * Unsupported Method.
1585     */
1586    public void signXML() throws SAMLException {
1587        throw new SAMLException(
1588                 FSUtils.BUNDLE_NAME,"unsupportedOperation",null);
1589    }
1590    
1591    /**
1592     * Sets the Signature of the Element passed.
1593     *
1594     * @param elem the Document Element.
1595     * @return true if success otherwise false.
1596     */
1597    public boolean setSignature(Element elem) {
1598        signatureString = XMLUtils.print(elem);
1599        return super.setSignature(elem);
1600    }
1601}