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.Objects; 023import java.util.Set; 024import java.util.UUID; 025 026import com.nimbusds.oauth2.sdk.token.AccessToken; 027import net.minidev.json.JSONObject; 028 029 030/** 031 * Distributed OpenID claims set. 032 * 033 * <p>Example distributed claims with an access token (included in a UserInfo 034 * response): 035 * 036 * <pre> 037 * { 038 * "_claim_names" : { "credit_score" : "src1" }, 039 * "_claim_sources" : { "src1" : { "endpoint" : "https://creditagency.example.com/claims_here", 040 * "access_token" : "ksj3n283dke" } } 041 * } 042 * </pre> 043 * 044 * <p>Example distributed claims without a specified access token (included in 045 * a UserInfo response): 046 * 047 * <pre> 048 * { 049 * "_claim_names" : { "payment_info" : "src2", 050 * "shipping_address" : "src2" }, 051 * "_claim_sources" : { "src2" : { "endpoint" : "https://bank.example.com/claim_source" } } 052 * } 053 * </pre> 054 * 055 * <p>Related specifications: 056 * 057 * <ul> 058 * <li>OpenID Connect Core 1.0 059 * </ul> 060 */ 061public class DistributedClaims extends ExternalClaims { 062 063 064 /** 065 * The claims source endpoint. 066 */ 067 private final URI sourceEndpoint; 068 069 070 /** 071 * Access token for retrieving the claims at the source URI, 072 * {@code null} if not specified. 073 */ 074 private final AccessToken accessToken; 075 076 077 /** 078 * Creates a new aggregated OpenID claims instance, the claims source 079 * identifier is set to a GUUID string. 080 * 081 * @param names The claim names. Must not be {@code null} or 082 * empty. 083 * @param sourceEndpoint The claims source endpoint. Must not be 084 * {@code null}. 085 * @param accessToken Access token for retrieving the claims at the 086 * source endpoint, {@code null} if not 087 * specified. 088 */ 089 public DistributedClaims(final Set<String> names, final URI sourceEndpoint, final AccessToken accessToken) { 090 091 this(UUID.randomUUID().toString(), names, sourceEndpoint, accessToken); 092 } 093 094 095 /** 096 * Creates a new aggregated OpenID claims instance. 097 * 098 * @param sourceID Identifier for the claims source. Must not be 099 * {@code null} or empty string. 100 * @param names The claim names. Must not be {@code null} or 101 * empty. 102 * @param sourceEndpoint The claims source endpoint. Must not be 103 * {@code null}. 104 * @param accessToken Access token for retrieving the claims at the 105 * source endpoint, {@code null} if not 106 * specified. 107 */ 108 public DistributedClaims(final String sourceID, final Set<String> names, final URI sourceEndpoint, final AccessToken accessToken) { 109 110 super(sourceID, names); 111 this.sourceEndpoint = Objects.requireNonNull(sourceEndpoint); 112 this.accessToken = accessToken; 113 } 114 115 116 /** 117 * Returns the claims source endpoint. 118 * 119 * @return The claims source endpoint. 120 */ 121 public URI getSourceEndpoint() { 122 123 return sourceEndpoint; 124 } 125 126 127 /** 128 * Returns the access token for retrieving the claims at the source 129 * endpoint. 130 * 131 * @return The access token for retrieving the claims at the source 132 * endpoint, {@code null} if not specified. 133 */ 134 public AccessToken getAccessToken() { 135 136 return accessToken; 137 } 138 139 140 @Override 141 void mergeInto(final JSONObject jsonObject) { 142 143 JSONObject claimNamesObject = new JSONObject(); 144 145 for (String name: getNames()) { 146 claimNamesObject.put(name, getSourceID()); 147 } 148 149 if (jsonObject.containsKey("_claim_names")) { 150 ((JSONObject) jsonObject.get("_claim_names")).putAll(claimNamesObject); 151 } else { 152 jsonObject.put("_claim_names", claimNamesObject); 153 } 154 155 JSONObject sourceSpec = new JSONObject(); 156 sourceSpec.put("endpoint", getSourceEndpoint().toString()); 157 if (getAccessToken() != null) { 158 sourceSpec.put("access_token", getAccessToken().getValue()); 159 } 160 JSONObject claimSourcesObject = new JSONObject(); 161 claimSourcesObject.put(getSourceID(), sourceSpec); 162 163 if (jsonObject.containsKey("_claim_sources")) { 164 ((JSONObject) jsonObject.get("_claim_sources")).putAll(claimSourcesObject); 165 } else { 166 jsonObject.put("_claim_sources", claimSourcesObject); 167 } 168 } 169}