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