001/* 002 * oauth2-oidc-sdk 003 * 004 * Copyright 2012-2016, Connect2id Ltd and contributors. 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); you may not use 007 * this file except in compliance with the License. You may obtain a copy of the 008 * License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software distributed 013 * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR 014 * CONDITIONS OF ANY KIND, either express or implied. See the License for the 015 * specific language governing permissions and limitations under the License. 016 */ 017 018package com.nimbusds.openid.connect.sdk.claims; 019 020 021import java.net.URI; 022import java.util.Set; 023import java.util.UUID; 024 025import com.nimbusds.oauth2.sdk.token.AccessToken; 026import net.minidev.json.JSONObject; 027 028 029/** 030 * Distributed OpenID claims set. 031 * 032 * <p>Example distributed claims with an access token (included in a UserInfo 033 * response): 034 * 035 * <pre> 036 * { 037 * "_claim_names" : { "credit_score" : "src1" }, 038 * "_claim_sources" : { "src1" : { "endpoint" : "https://creditagency.example.com/claims_here", 039 * "access_token" : "ksj3n283dke" } } 040 * } 041 * </pre> 042 * 043 * <p>Example distributed claims without a specified access token (included in 044 * a UserInfo response): 045 * 046 * <pre> 047 * { 048 * "_claim_names" : { "payment_info" : "src2", 049 * "shipping_address" : "src2" }, 050 * "_claim_sources" : { "src2" : { "endpoint" : "https://bank.example.com/claim_source" } } 051 * } 052 * </pre> 053 * 054 * <p>Related specifications: 055 * 056 * <ul> 057 * <li>OpenID Connect Core 1.0, sections 5.1 and 5.6.2. 058 * </ul> 059 */ 060public class DistributedClaims extends ExternalClaims { 061 062 063 /** 064 * The claims source endpoint. 065 */ 066 private final URI sourceEndpoint; 067 068 069 /** 070 * Access token for retrieving the claims at the source URI, 071 * {@code null} if not specified. 072 */ 073 private final AccessToken accessToken; 074 075 076 /** 077 * Creates a new aggregated OpenID claims instance, the claims source 078 * identifier is set to a GUUID string. 079 * 080 * @param names The claim names. Must not be {@code null} or 081 * empty. 082 * @param sourceEndpoint The claims source endpoint. Must not be 083 * {@code null}. 084 * @param accessToken Access token for retrieving the claims at the 085 * source endpoint, {@code null} if not 086 * specified. 087 */ 088 public DistributedClaims(final Set<String> names, final URI sourceEndpoint, final AccessToken accessToken) { 089 090 this(UUID.randomUUID().toString(), names, sourceEndpoint, accessToken); 091 } 092 093 094 /** 095 * Creates a new aggregated OpenID claims instance. 096 * 097 * @param sourceID Identifier for the claims source. Must not be 098 * {@code null} or empty string. 099 * @param names The claim names. Must not be {@code null} or 100 * empty. 101 * @param sourceEndpoint The claims source endpoint. Must not be 102 * {@code null}. 103 * @param accessToken Access token for retrieving the claims at the 104 * source endpoint, {@code null} if not 105 * specified. 106 */ 107 public DistributedClaims(final String sourceID, final Set<String> names, final URI sourceEndpoint, final AccessToken accessToken) { 108 109 super(sourceID, names); 110 111 if (sourceEndpoint == null) { 112 throw new IllegalArgumentException("The claims source URI must not be null"); 113 } 114 115 this.sourceEndpoint = sourceEndpoint; 116 117 this.accessToken = accessToken; 118 } 119 120 121 /** 122 * Returns the claims source endpoint. 123 * 124 * @return The claims source endpoint. 125 */ 126 public URI getSourceEndpoint() { 127 128 return sourceEndpoint; 129 } 130 131 132 /** 133 * Returns the access token for retrieving the claims at the source 134 * endpoint. 135 * 136 * @return The access token for retrieving the claims at the source 137 * endpoint, {@code null} if not specified. 138 */ 139 public AccessToken getAccessToken() { 140 141 return accessToken; 142 } 143 144 145 @Override 146 void mergeInto(final JSONObject jsonObject) { 147 148 JSONObject claimNamesObject = new JSONObject(); 149 150 for (String name: getNames()) { 151 claimNamesObject.put(name, getSourceID()); 152 } 153 154 if (jsonObject.containsKey("_claim_names")) { 155 ((JSONObject) jsonObject.get("_claim_names")).putAll(claimNamesObject); 156 } else { 157 jsonObject.put("_claim_names", claimNamesObject); 158 } 159 160 JSONObject sourceSpec = new JSONObject(); 161 sourceSpec.put("endpoint", getSourceEndpoint().toString()); 162 if (getAccessToken() != null) { 163 sourceSpec.put("access_token", getAccessToken().getValue()); 164 } 165 JSONObject claimSourcesObject = new JSONObject(); 166 claimSourcesObject.put(getSourceID(), sourceSpec); 167 168 if (jsonObject.containsKey("_claim_sources")) { 169 ((JSONObject) jsonObject.get("_claim_sources")).putAll(claimSourcesObject); 170 } else { 171 jsonObject.put("_claim_sources", claimSourcesObject); 172 } 173 } 174}