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: FSAuthnResponse.java,v 1.2 2008/06/25 05:46:43 qcheng Exp $ 026 * 027 */ 028 029 030package com.sun.identity.federation.message; 031 032import com.sun.identity.federation.message.common.FSMsgException; 033import com.sun.identity.federation.common.FSUtils; 034import com.sun.identity.federation.common.IFSConstants; 035import com.sun.identity.saml.common.SAMLException; 036import com.sun.identity.saml.common.SAMLConstants; 037import com.sun.identity.saml.common.SAMLResponderException; 038import com.sun.identity.saml.common.SAMLVersionMismatchException; 039import com.sun.identity.saml.protocol.Response; 040import com.sun.identity.saml.protocol.Status; 041import com.sun.identity.saml.xmlsig.XMLSignatureManager; 042import com.sun.identity.shared.encode.Base64; 043import com.sun.identity.shared.DateUtils; 044import com.sun.identity.shared.xml.XMLUtils; 045import java.io.IOException; 046import java.text.ParseException; 047import java.util.List; 048import java.util.Collections; 049import java.util.ArrayList; 050import java.util.Iterator; 051import java.util.Date; 052import org.w3c.dom.Element; 053import org.w3c.dom.Node; 054import org.w3c.dom.NodeList; 055import org.w3c.dom.Document; 056 057/** 058 * The class <code>FSAuthnResponse</code> creates and parses the 059 * Liberty Response. This class extends the <code>SAML</code> 060 * <code>Response</code>. 061 * 062 * @supported.all.api 063 */ 064 065public class FSAuthnResponse extends Response { 066 067 private String providerId = null; 068 protected String relayState = null; 069 protected String consentURI = null; 070 protected int minorVersion = 0; 071 protected String id = null; 072 protected Element domElement = null; 073 074 075 /** 076 * Constructor to create <code>FSAuthnResponse</code> object. 077 * 078 * @param responseID value of the <code>ResponseID</code> attribute. 079 * @param inResponseTo value of the <code>inResponseTo</code> attribute. 080 * @param status the <code>Status</code> object. 081 * @param contents List of Assertions in the response. 082 * It could be null when there are no Assertions. 083 * @param relayState value of the <code>RelayState</code> attribute. 084 * @throws FSMsgException on error. 085 * @throws SAMLException on error. 086 */ 087 public FSAuthnResponse(String responseID,String inResponseTo, 088 Status status, List contents, String relayState) 089 throws SAMLException, FSMsgException { 090 super( responseID, inResponseTo, status, contents); 091 setIssueInstant(new Date()); 092 this.relayState = relayState; 093 } 094 095 /** 096 * Creates <code>FSAuthnResponse</code> object from XML Schema. 097 * 098 * @param xml the XML Schema for this object. 099 * @throws <code>SAMLException</code> on error. 100 * @throws FSMsgException on error. 101 */ 102 public static FSAuthnResponse parseAuthnResponseXML( 103 String xml) throws SAMLException, FSMsgException { 104 // parse the xml string 105 FSUtils.debug.message("FSAuthnResponse.parseAuthnResponseXML: Called"); 106 Element root; 107 Document doc = XMLUtils.toDOMDocument(xml, FSUtils.debug); 108 if (doc == null) { 109 if (FSUtils.debug.messageEnabled()) { 110 FSUtils.debug.message( 111 "FSAuthnResponse.parseXML:Error " 112 + "while parsing input xml string"); 113 } 114 throw new FSMsgException("parseError",null); 115 } 116 root = doc.getDocumentElement(); 117 return new FSAuthnResponse(root); 118 } 119 120 /** 121 * Constructor creates <code>FSAuthnResponse</code> object from 122 * Document Element. 123 * 124 * @param root the Document Element 125 * @throws SAMLException on error. 126 * @throws FSMsgException on error. 127 */ 128 public FSAuthnResponse(Element root) throws SAMLException, FSMsgException { 129 // Make sure this is a Response 130 FSUtils.debug.message("FSAuthnResponse(Element): Called"); 131 if (root == null) { 132 FSUtils.debug.message("FSAuthnResponse(Element): " 133 + "Input paramenter (root) is null"); 134 throw new FSMsgException("nullInput",null); 135 } 136 String tag = null; 137 if (((tag = root.getLocalName()) == null) || 138 (!tag.equals(IFSConstants.AUTHN_RESPONSE))) { 139 FSUtils.debug.message("FSAuthnResponse(Element): " 140 + "Root element name is not AuthnResponse"); 141 throw new FSMsgException("wrongInput",null); 142 } 143 domElement = root; 144 consentURI = root.getAttribute(IFSConstants.CONSENT); 145 146 // Attribute ResponseID 147 id = root.getAttribute(IFSConstants.ID); 148 responseID = root.getAttribute(IFSConstants.RESPONSE_ID); 149 if ((responseID == null) || (responseID.length() == 0)) { 150 if (FSUtils.debug.messageEnabled()) { 151 FSUtils.debug.message("FSAuthnResponse(Element): " 152 + "AuthnResponse doesn't have ResponseID attribute"); 153 } 154 String[] args = { IFSConstants.RESPONSE_ID }; 155 throw new FSMsgException("missingAttribute",args); 156 } 157 158 inResponseTo = root.getAttribute(IFSConstants.IN_RESPONSE_TO); 159 if (inResponseTo == null) { 160 if (FSUtils.debug.messageEnabled()) { 161 FSUtils.debug.message("FSAuthnResponse(Element): " 162 + "AuthnResponse doesn't have InResponseTo attribute"); 163 } 164 } 165 166 // Attribute IssueInstant 167 String instantString = root.getAttribute(IFSConstants.ISSUE_INSTANT); 168 169 if ((instantString == null) || (instantString.length() == 0)) { 170 FSUtils.debug.message("FSAuthnResponse(Element): " 171 + " missing IssueInstant"); 172 String[] args = { IFSConstants.ISSUE_INSTANT }; 173 throw new FSMsgException("missingAttribute",args); 174 } else { 175 try { 176 issueInstant = DateUtils.stringToDate(instantString); 177 } catch (ParseException e) { 178 FSUtils.debug.message( 179 "FSAuthnResponse(Element): could not parse IssueInstant",e); 180 throw new FSMsgException("wrongInput",null); 181 } 182 } 183 184 parseMajorVersion(root.getAttribute(IFSConstants.MAJOR_VERSION)); 185 parseMinorVersion(root.getAttribute(IFSConstants.MINOR_VERSION)); 186 187 setRecipient(root.getAttribute(IFSConstants.RECIPIENT)); 188 189 NodeList nl = root.getChildNodes(); 190 Node child; 191 String childName; 192 int length = nl.getLength(); 193 for (int i = 0; i < length; i++) { 194 child = nl.item(i); 195 if ((childName = child.getLocalName()) != null) { 196 if (childName.equals(IFSConstants.STATUS)) { 197 if (status != null) { 198 if (FSUtils.debug.messageEnabled()) { 199 FSUtils.debug.message("FSAuthnResponse(Element): " 200 + "included more than one <Status>"); 201 } 202 throw new FSMsgException("moreElement",null); 203 } 204 status = new Status((Element) child); 205 } else if (childName.equals(IFSConstants.ASSERTION)) { 206 if (assertions == Collections.EMPTY_LIST) { 207 assertions = new ArrayList(); 208 } 209 assertions.add(new FSAssertion((Element) child)); 210 } else if (childName.equals(IFSConstants.RELAY_STATE)) { 211 // make sure the providerId is not assigned already 212 if (relayState != null) { 213 if (FSUtils.debug.messageEnabled()) { 214 FSUtils.debug.message("FSAuthnResponse(Element): " 215 + "should contain only one RelayState."); 216 } 217 throw new FSMsgException("wrongInput",null); 218 } 219 relayState = XMLUtils.getElementValue((Element) child); 220 } else if (childName.equals(IFSConstants.PROVIDER_ID)) { 221 if (providerId != null && providerId.length() != 0) { 222 if (FSUtils.debug.messageEnabled()) { 223 FSUtils.debug.message("FSAuthnResponse(Element): " 224 + "should contain only one ProviderID."); 225 } 226 throw new FSMsgException("wrongInput",null); 227 } 228 providerId = XMLUtils.getElementValue((Element) child); 229 } else { 230 if (FSUtils.debug.messageEnabled()) { 231 FSUtils.debug.message("FSAuthnResponse(Element): " 232 + "included wrong element: " + childName); 233 } 234 throw new FSMsgException("wrongInput",null); 235 } 236 } // end if childName != null 237 } // end for loop 238 239 if (status == null) { 240 FSUtils.debug.message("FSAuthnResponse(Element): " 241 + "missing element <Status>."); 242 throw new FSMsgException("missingElement",null); 243 } 244 //check for signature 245 List signs = XMLUtils.getElementsByTagNameNS1(root, 246 SAMLConstants.XMLSIG_NAMESPACE_URI, 247 SAMLConstants.XMLSIG_ELEMENT_NAME); 248 int signsSize = signs.size(); 249 if (signsSize == 1) { 250 Element elem = (Element)signs.get(0); 251 setSignature(elem); 252 xmlString = XMLUtils.print(root); 253 signed = true; 254 } else if (signsSize != 0) { 255 if (FSUtils.debug.messageEnabled()) { 256 FSUtils.debug.message("FSAuthnResponse(Element): " 257 + "included more than one Signature element."); 258 } 259 throw new FSMsgException("moreElement",null); 260 } 261 //end check for signature 262 } 263 264 /** 265 * Returns the value of the <code>id</code> attribute. 266 * 267 * @return the value of <code>id</code> attribute. 268 * @see #setID(String) 269 */ 270 public String getID() { 271 return id; 272 } 273 274 /** 275 * Sets the value of the <code>id</code> attribute. 276 * 277 * @param id the new value of <code>id</code> attribute. 278 * @see #getID 279 */ 280 public void setID(String id) { 281 this.id = id; 282 } 283 284 /** 285 * Returns the <code>ProviderID</code> attribute value. 286 * 287 * @return value of the <code>ProviderID</code> attribute. 288 * @see #setProviderId(String) 289 */ 290 public String getProviderId() { 291 return providerId; 292 } 293 294 /** 295 * Sets the <code>ProviderID</code> attribute value. 296 * 297 * @param provId new value of <code>ProviderID</code> attribute. 298 * @see #getProviderId 299 */ 300 public void setProviderId(String provId) { 301 providerId = provId; 302 } 303 304 /** 305 * Returns a signed XML Representation of this object. 306 * 307 * @return a signed XML Representation of this object. 308 */ 309 public String getSignedXMLString(){ 310 return xmlString; 311 } 312 313 /** 314 * Returns the Signature string. 315 * 316 * @return the Signature string. 317 */ 318 public String getSignatureString(){ 319 return signatureString; 320 } 321 322 /** 323 * Returns the value <code>MinorVersion</code> attribute. 324 * 325 * @return the value <code>MinorVersion</code> attribute. 326 * @see #setMinorVersion(int) 327 */ 328 public int getMinorVersion() { 329 return minorVersion; 330 } 331 332 /** 333 * Returns the value of <code>MajorVersion</code> attribute. 334 * 335 * @param version the value of <code>MajorVersion</code> attribute. 336 * @see #getMinorVersion 337 */ 338 public void setMinorVersion(int version) { 339 minorVersion = version; 340 } 341 342 /** 343 * Returns the value of the <code>consent</code> attribute. 344 * 345 * @return value of <code>consent</code> attribute. 346 * @see #setConsentURI(String) 347 */ 348 349 public String getConsentURI() { 350 return consentURI; 351 } 352 353 /** 354 * Sets the value of the <code>consent</code> attribute. 355 * 356 * @param consent new value of <code>consent</code> attribute. 357 * @see #getConsentURI 358 */ 359 public void setConsentURI(String consent) { 360 this.consentURI = consent; 361 } 362 363 /** 364 * Returns the Document Element for this object. 365 * 366 * @return the Document Element for this object. 367 */ 368 public Element getDOMElement() { 369 return domElement; 370 } 371 372 /** 373 * Parses the input and sets the <code>MajorVersion</code>. 374 * 375 * @param majorVer value of <code>MajorVersion</code> attribute to be set. 376 * @throws FSMsgException on error. 377 * @throws SAMLException if the version is incorrect. 378 */ 379 private void parseMajorVersion(String majorVer) 380 throws SAMLException, FSMsgException { 381 try { 382 majorVersion = Integer.parseInt(majorVer); 383 } catch (NumberFormatException e) { 384 if (FSUtils.debug.messageEnabled()) { 385 FSUtils.debug.message("FSAuthnResponse(Element): invalid " 386 + "MajorVersion", e); 387 } 388 throw new FSMsgException("wrongInput",null); 389 } 390 391 if (majorVersion != SAMLConstants.PROTOCOL_MAJOR_VERSION) { 392 if (majorVersion > SAMLConstants.PROTOCOL_MAJOR_VERSION) { 393 if (FSUtils.debug.messageEnabled()) { 394 FSUtils.debug.message( 395 "FSAuthnResponse(Element):MajorVersion of" 396 + " the Response is too high."); 397 } 398 throw new SAMLVersionMismatchException(FSUtils.BUNDLE_NAME, 399 "responseVersionTooHigh",null); 400 } else { 401 if (FSUtils.debug.messageEnabled()) { 402 FSUtils.debug.message( 403 "FSAuthnResponse(Element):MajorVersion of" 404 + " the Response is too low."); 405 } 406 throw new SAMLVersionMismatchException( 407 FSUtils.BUNDLE_NAME,"responseVersionTooLow",null); 408 } 409 } 410 } 411 412 /** 413 * Parses the input and set the <code>MinorVersion</code>. 414 * 415 * @param minorVer value of <code>MinorVersion</code> attribute to be set. 416 * @throws FSMsgException on error. 417 * @throws SAMLException if the version is incorrect. 418 */ 419 private void parseMinorVersion( 420 String minorVer) throws SAMLException, FSMsgException { 421 try { 422 minorVersion = Integer.parseInt(minorVer); 423 } catch (NumberFormatException e) { 424 if (FSUtils.debug.messageEnabled()) { 425 FSUtils.debug.message("FSAuthnResponse(Element): invalid " 426 + "MinorVersion", e); 427 } 428 throw new FSMsgException("wrongInput",null); 429 } 430 431 if (minorVersion > IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) { 432 if(FSUtils.debug.messageEnabled()) { 433 FSUtils.debug.message("FSAuthnResponse.checkMinorVersion:"+ 434 " Minor Version of the AuthnResponse is too high."); 435 } 436 throw new FSMsgException("requestVersionTooHigh",null); 437 } else if (minorVersion < IFSConstants.FF_11_PROTOCOL_MINOR_VERSION) { 438 if(FSUtils.debug.messageEnabled()) { 439 FSUtils.debug.message("FSAuthnResponse.checkMinorVersion:" + 440 " Minor Version of the AuthnResponse is too low."); 441 } 442 throw new FSMsgException("requestVersionTooLow",null); 443 } 444 } 445 446 /** 447 * Returns the <code>RelayState</code> attribute in the Response. 448 * 449 * @return the <code>RelayState</code> attribute in the Response. 450 */ 451 public String getRelayState() { 452 return relayState; 453 } 454 455 /** 456 * Returns the string representation of this object. 457 * This method translates the response to an XML document string based on 458 * the Response schema described above. 459 * 460 * @return An XML String representing the response. NOTE: this is a 461 * complete SAML response xml string with ResponseID, 462 * MajorVersion, etc. 463 */ 464 public String toXMLString() throws FSMsgException { 465 return this.toXMLString(true, true); 466 } 467 468 /** 469 * Returns a String representation of the <samlp:Response> element. 470 * 471 * @param includeNS : Determines whether or not the namespace qualifier 472 * is prepended to the Element when converted 473 * @param declareNS : Determines whether or not the namespace is declared 474 * within the Element. 475 * @return A string containing the valid XML for this element 476 */ 477 public String toXMLString(boolean includeNS, boolean declareNS) 478 throws FSMsgException { 479 return toXMLString(includeNS, declareNS, false); 480 } 481 482 /** 483 * Returns a String representation of the <samlp:Response> element. 484 * 485 * @param includeNS Determines whether or not the namespace qualifier 486 * is prepended to the Element when converted 487 * @param declareNS Determines whether or not the namespace is declared 488 * within the Element. 489 * @param includeHeader Determines whether the output include the xml 490 * declaration header. 491 * @return A string containing the valid XML for this element 492 */ 493 public String toXMLString(boolean includeNS, 494 boolean declareNS, 495 boolean includeHeader) throws FSMsgException { 496 FSUtils.debug.message("FSAuthnResponse.toXMLString(3): Called"); 497 498 if((providerId == null) || (providerId.length() == 0)){ 499 FSUtils.debug.error("FSAuthnResponse.toXMLString: " 500 + "providerId is null "); 501 throw new FSMsgException("nullProviderID",null); 502 } 503 504 StringBuffer xml = new StringBuffer(300); 505 if (includeHeader) { 506 xml.append(IFSConstants.XML_PREFIX) 507 .append(SAMLConstants.DEFAULT_ENCODING).append("\" ?>\n") 508 .append(IFSConstants.QUOTE) 509 .append(IFSConstants.QUESTION_MARK) 510 .append(IFSConstants.RIGHT_ANGLE) 511 .append(IFSConstants.NL); 512 } 513 String prefixSAML = ""; 514 String prefixLIB = ""; 515 String prefixSAML_PROTOCOL = ""; 516 String uriSAML_PROTOCOL = ""; 517 String uriSAML = ""; 518 String uriLIB = ""; 519 String uriDS=""; 520 String uriXSI=""; 521 522 if (includeNS) { 523 prefixLIB = IFSConstants.LIB_PREFIX; 524 prefixSAML = IFSConstants.ASSERTION_PREFIX; 525 prefixSAML_PROTOCOL = IFSConstants.PROTOCOL_PREFIX; 526 } 527 if (declareNS) { 528 if(minorVersion == IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) { 529 uriLIB = IFSConstants.LIB_12_NAMESPACE_STRING; 530 } else { 531 uriLIB = IFSConstants.LIB_NAMESPACE_STRING; 532 } 533 uriSAML = IFSConstants.assertionDeclareStr; 534 uriSAML_PROTOCOL = IFSConstants.PROTOCOL_NAMESPACE_STRING; 535 uriDS = IFSConstants.DSSAMLNameSpace; 536 uriXSI = IFSConstants.XSI_NAMESPACE_STRING; 537 } 538 539 String instantString = DateUtils.toUTCDateFormat(issueInstant); 540 541 if((responseID != null) && (inResponseTo != null)){ 542 xml.append(IFSConstants.LEFT_ANGLE) 543 .append(prefixLIB) 544 .append(IFSConstants.AUTHN_RESPONSE) 545 .append(uriLIB) 546 .append(uriSAML) 547 .append(uriSAML_PROTOCOL) 548 .append(IFSConstants.SPACE) 549 .append(uriDS) 550 .append(IFSConstants.SPACE) 551 .append(uriXSI) 552 .append(IFSConstants.SPACE) 553 .append(IFSConstants.RESPONSE_ID) 554 .append(IFSConstants.EQUAL_TO) 555 .append(IFSConstants.QUOTE) 556 .append(responseID) 557 .append(IFSConstants.QUOTE) 558 .append(IFSConstants.SPACE); 559 560 if ((inResponseTo != null) && (inResponseTo.length() != 0)) { 561 xml.append(IFSConstants.SPACE) 562 .append(IFSConstants.IN_RESPONSE_TO) 563 .append(IFSConstants.EQUAL_TO) 564 .append(IFSConstants.QUOTE) 565 .append(inResponseTo) 566 .append(IFSConstants.QUOTE); 567 } 568 if (minorVersion == IFSConstants.FF_11_PROTOCOL_MINOR_VERSION && 569 id != null && (id.length() > 0)) { 570 xml.append(IFSConstants.SPACE) 571 .append(IFSConstants.ID) 572 .append(IFSConstants.EQUAL_TO) 573 .append(IFSConstants.QUOTE) 574 .append(id) 575 .append(IFSConstants.QUOTE); 576 } 577 xml.append(IFSConstants.SPACE) 578 .append(IFSConstants.MAJOR_VERSION) 579 .append(IFSConstants.EQUAL_TO) 580 .append(IFSConstants.QUOTE) 581 .append(majorVersion) 582 .append(IFSConstants.QUOTE) 583 .append(IFSConstants.SPACE) 584 .append(IFSConstants.MINOR_VERSION) 585 .append(IFSConstants.EQUAL_TO) 586 .append(IFSConstants.QUOTE) 587 .append(minorVersion) 588 .append(IFSConstants.QUOTE) 589 .append(IFSConstants.SPACE) 590 .append(IFSConstants.ISSUE_INSTANT) 591 .append(IFSConstants.EQUAL_TO) 592 .append(IFSConstants.QUOTE) 593 .append(instantString) 594 .append(IFSConstants.QUOTE); 595 596 if (consentURI != null) { 597 xml.append(IFSConstants.SPACE) 598 .append(IFSConstants.CONSENT) 599 .append(IFSConstants.EQUAL_TO) 600 .append(IFSConstants.QUOTE) 601 .append(consentURI) 602 .append(IFSConstants.QUOTE) 603 .append(IFSConstants.SPACE); 604 } 605 if ((recipient != null) && (recipient.length() != 0)) { 606 xml.append(IFSConstants.SPACE) 607 .append(IFSConstants.RECIPIENT) 608 .append(IFSConstants.EQUAL_TO) 609 .append(IFSConstants.QUOTE) 610 .append(recipient) 611 .append(IFSConstants.QUOTE) 612 .append(IFSConstants.SPACE); 613 } 614 xml.append(IFSConstants.RIGHT_ANGLE); 615 } 616 617 if (signed) { 618 if (signatureString != null && signatureString.length() != 0) { 619 xml.append(signatureString); 620 } else if (signature != null) { 621 signatureString = XMLUtils.print(signature); 622 xml.append(signatureString); 623 } 624 } 625 626 if (status != null) { 627 xml.append(status.toString(includeNS, false)); 628 } 629 630 if ((assertions != null) && (assertions != Collections.EMPTY_LIST)) { 631 Iterator j = assertions.iterator(); 632 while (j.hasNext()) { 633 xml.append(((FSAssertion) j.next()) 634 .toXMLString(true,declareNS)); 635 } 636 } 637 638 xml.append(IFSConstants.LEFT_ANGLE) 639 .append(prefixLIB) 640 .append(IFSConstants.PROVIDER_ID) 641 .append(IFSConstants.RIGHT_ANGLE) 642 .append(providerId) 643 .append(IFSConstants.START_END_ELEMENT) 644 .append(prefixLIB) 645 .append(IFSConstants.PROVIDER_ID) 646 .append(IFSConstants.RIGHT_ANGLE); 647 648 if (relayState != null && relayState.length() != 0) { 649 xml.append(IFSConstants.LEFT_ANGLE) 650 .append(prefixLIB) 651 .append(IFSConstants.RELAY_STATE) 652 .append(IFSConstants.RIGHT_ANGLE) 653 .append(XMLUtils.escapeSpecialCharacters(relayState)) 654 .append(IFSConstants.START_END_ELEMENT) 655 .append(prefixLIB) 656 .append(IFSConstants.RELAY_STATE) 657 .append(IFSConstants.RIGHT_ANGLE); 658 } 659 660 xml.append(IFSConstants.START_END_ELEMENT) 661 .append(prefixLIB) 662 .append(IFSConstants.AUTHN_RESPONSE) 663 .append(IFSConstants.RIGHT_ANGLE) 664 .append(IFSConstants.NL); 665 666 return xml.toString(); 667 } 668 669 /** 670 * Returns <code>FSAutnResponse</code> object by parsing a 671 * <code>Base64</code> encoding XML string. 672 * 673 * 674 * @param encodedRes the <code>Base64</code> encoded string. 675 * @return <code>FSAuthnResponse</code> object. 676 * @throws FSMsgException if there is an error parsing 677 * the <code>Base64</code> encoded string. 678 * @throws SAMLException if there is an error creating 679 * the <code>FSAuthnResponse</code> object. 680 */ 681 public static FSAuthnResponse parseBASE64EncodedString(String encodedRes) 682 throws FSMsgException, SAMLException { 683 FSUtils.debug.message( 684 "FSAuthnResponse.parseBASE64EncodedString: Called new"); 685 if(encodedRes != null){ 686 String decodedAuthnRes = new String(Base64.decode(encodedRes)); 687 if (FSUtils.debug.messageEnabled()) { 688 FSUtils.debug.message( 689 "FSAuthnResponse.parseBASE64EncodedString: " 690 + "Decoded AuthnResponse message: \n" 691 + decodedAuthnRes); 692 } 693 return parseAuthnResponseXML(decodedAuthnRes); 694 } else { 695 if (FSUtils.debug.messageEnabled()) { 696 FSUtils.debug.message( 697 "FSAuthnResponse.parseBASE64EncodedString: " 698 + "null String passed in as argument."); 699 } 700 throw new FSMsgException("nullInput",null); 701 } 702 } 703 704 /** 705 * Returns a <code>Base64</code> encoded string representing this 706 * object. 707 * 708 * @return a <code>Base64</code> encoded string representing this 709 * object. 710 * @throws FSMsgException if there is an error creating 711 * a <code>Base64</code> encoded string. 712 */ 713 public String toBASE64EncodedString() throws FSMsgException { 714 FSUtils.debug.message("FSAuthnResponse.toBASE64EncodedString: Called"); 715 if ((responseID == null) || (responseID.length() == 0)){ 716 responseID = FSUtils.generateID(); 717 if (responseID == null) { 718 FSUtils.debug.error("FSAuthnResponse.toBASE64EncodedString: " 719 + "couldn't generate ResponseID."); 720 throw new FSMsgException("errorGenerateID",null); 721 } 722 } 723 return Base64.encode(this.toXMLString(true, true).getBytes()); 724 } 725 726 /** 727 * Signs the <code>Response</code>. 728 * 729 * @param certAlias the Certificate Alias 730 * @throws SAMLException if <code>Response</code> 731 * cannot be signed. 732 */ 733 public void signXML(String certAlias) throws SAMLException { 734 FSUtils.debug.message("FSAuthnResponse.signXML: Called"); 735 if (signed) { 736 if (FSUtils.debug.messageEnabled()) { 737 FSUtils.debug.message( 738 "FSAuthnResponse.signXML: the assertion is " 739 + "already signed."); 740 } 741 throw new SAMLResponderException( 742 FSUtils.BUNDLE_NAME,"alreadySigned",null); 743 } 744 if (certAlias == null || certAlias.length() == 0) { 745 throw new SAMLResponderException( 746 FSUtils.BUNDLE_NAME,"cannotFindCertAlias",null); 747 } 748 try{ 749 XMLSignatureManager manager = XMLSignatureManager.getInstance(); 750 if (minorVersion == IFSConstants.FF_11_PROTOCOL_MINOR_VERSION) { 751 signatureString = manager.signXML(this.toXMLString(true, true), 752 certAlias, 753 IFSConstants.DEF_SIG_ALGO, 754 IFSConstants.ID, 755 this.id, false); 756 } else if (minorVersion == 757 IFSConstants.FF_12_PROTOCOL_MINOR_VERSION) { 758 signatureString = manager.signXML( 759 this.toXMLString(true, true), 760 certAlias, IFSConstants.DEF_SIG_ALGO, 761 IFSConstants.RESPONSE_ID, 762 this.getResponseID(), false); 763 } else { 764 if (FSUtils.debug.messageEnabled()) { 765 FSUtils.debug.message("invalid minor version."); 766 } 767 } 768 signature = XMLUtils.toDOMDocument(signatureString, FSUtils.debug) 769 .getDocumentElement(); 770 signed = true; 771 xmlString = this.toXMLString(true, true); 772 } catch(Exception e) { 773 throw new SAMLResponderException(FSUtils.BUNDLE_NAME, 774 "signFailed",null); 775 } 776 } 777 778 /** 779 * Sets the <code>Element</code> signature. 780 * 781 * @param elem the <code>Element</code> object 782 * @return true if signature is set otherwise false 783 */ 784 public boolean setSignature(Element elem) { 785 signatureString = XMLUtils.print(elem); 786 return super.setSignature(elem); 787 } 788}