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; 019 020 021import java.util.*; 022 023import net.minidev.json.JSONObject; 024 025import com.nimbusds.oauth2.sdk.Scope; 026 027import com.nimbusds.openid.connect.sdk.claims.ClaimRequirement; 028import com.nimbusds.openid.connect.sdk.claims.ClaimsSetRequest; 029 030 031/** 032 * Standard OpenID Connect scope value. 033 * 034 * <p>Related specifications: 035 * 036 * <ul> 037 * <li>OpenID Connect Core 1.0, section 5.2. 038 * </ul> 039 */ 040public class OIDCScopeValue extends Scope.Value { 041 042 043 /** 044 * Informs the authorisation server that the client is making an OpenID 045 * Connect request (REQUIRED). This scope value requests access to the 046 * {@code sub} claim. 047 */ 048 public static final OIDCScopeValue OPENID = 049 new OIDCScopeValue("openid", Scope.Value.Requirement.REQUIRED, new String[]{"sub"}); 050 051 052 /** 053 * Requests that access to the end-user's default profile claims at the 054 * UserInfo endpoint be granted by the issued access token. These 055 * claims are: {@code name}, {@code family_name}, {@code given_name}, 056 * {@code middle_name}, {@code nickname}, {@code preferred_username}, 057 * {@code profile}, {@code picture}, {@code website}, {@code gender}, 058 * {@code birthdate}, {@code zoneinfo}, {@code locale}, and 059 * {@code updated_at}. 060 */ 061 public static final OIDCScopeValue PROFILE = 062 new OIDCScopeValue("profile", new String[]{"name", 063 "family_name", 064 "given_name", 065 "middle_name", 066 "nickname", 067 "preferred_username", 068 "profile", 069 "picture", 070 "website", 071 "gender", 072 "birthdate", 073 "zoneinfo", 074 "locale", 075 "updated_at"}); 076 077 078 /** 079 * Requests that access to the {@code email} and {@code email_verified} 080 * claims at the UserInfo endpoint be granted by the issued access 081 * token. 082 */ 083 public static final OIDCScopeValue EMAIL = 084 new OIDCScopeValue("email", new String[]{"email", "email_verified"}); 085 086 087 /** 088 * Requests that access to {@code address} claim at the UserInfo 089 * endpoint be granted by the issued access token. 090 */ 091 public static final OIDCScopeValue ADDRESS = 092 new OIDCScopeValue("address", new String[]{"address"}); 093 094 095 /** 096 * Requests that access to the {@code phone_number} and 097 * {@code phone_number_verified} claims at the UserInfo endpoint be 098 * granted by the issued access token. 099 */ 100 public static final OIDCScopeValue PHONE = 101 new OIDCScopeValue("phone", new String[]{"phone_number", 102 "phone_number_verified"}); 103 104 105 /** 106 * Requests that an OAuth 2.0 refresh token be issued that can be used 107 * to obtain an access token that grants access the end-user's UserInfo 108 * endpoint even when the user is not present (not logged in). 109 */ 110 public static final OIDCScopeValue OFFLINE_ACCESS = 111 new OIDCScopeValue("offline_access", null); 112 113 114 /** 115 * Returns the standard OpenID Connect scope values declared in this 116 * class. 117 * 118 * @return The standard OpenID Connect scope values. 119 */ 120 public static OIDCScopeValue[] values() { 121 122 return new OIDCScopeValue[]{ OPENID, PROFILE, EMAIL, ADDRESS, PHONE, OFFLINE_ACCESS }; 123 } 124 125 126 /** 127 * The names of the associated claims, {@code null} if not applicable. 128 */ 129 private final Set<String> claims; 130 131 132 /** 133 * Creates a new OpenID Connect scope value. 134 * 135 * @param value The scope value. Must not be {@code null}. 136 * @param requirement The requirement. Must not be {@code null}. 137 * @param claims The names of the associated claims, {@code null} 138 * if not applicable. 139 */ 140 private OIDCScopeValue(final String value, 141 final Scope.Value.Requirement requirement, 142 final String[] claims) { 143 144 super(value, requirement); 145 146 if (claims != null) 147 this.claims = Collections.unmodifiableSet(new LinkedHashSet<>(Arrays.asList(claims))); 148 else 149 this.claims = null; 150 } 151 152 153 /** 154 * Creates a new OpenID Connect scope value. The requirement is set to 155 * {@link OIDCScopeValue.Requirement#OPTIONAL optional}. 156 * 157 * @param value The scope value. Must not be {@code null}. 158 * @param claims The names of the associated claims. Must not be 159 * {@code null}. 160 */ 161 private OIDCScopeValue(final String value, 162 final String[] claims) { 163 164 this(value, Scope.Value.Requirement.OPTIONAL, claims); 165 } 166 167 168 /** 169 * Returns the names of the associated claims. 170 * 171 * @return The names of the associated claims, {@code null} if not 172 * applicable. 173 */ 174 public Set<String> getClaimNames() { 175 176 return claims; 177 } 178 179 180 /** 181 * Gets the claims request JSON object for this OpenID Connect scope 182 * value. 183 * 184 * <p>See OpenID Connect Core 1.0, section 5.1. 185 * 186 * <p>Example JSON object for "openid" scope value: 187 * 188 * <pre> 189 * { 190 * "sub" : { "essential" : true } 191 * } 192 * </pre> 193 * 194 * <p>Example JSON object for "email" scope value: 195 * 196 * <pre> 197 * { 198 * "email" : null, 199 * "email_verified" : null 200 * } 201 * </pre> 202 * 203 * @return The claims request JSON object, {@code null} if not 204 * applicable. 205 */ 206 public JSONObject toClaimsRequestJSONObject() { 207 208 JSONObject req = new JSONObject(); 209 210 if (claims == null) 211 return null; 212 213 for (String claim: claims) { 214 215 if (getRequirement() == Scope.Value.Requirement.REQUIRED) { 216 217 // Essential (applies to OPENID - sub only) 218 JSONObject details = new JSONObject(); 219 details.put("essential", true); 220 req.put(claim, details); 221 222 } else { 223 // Voluntary 224 req.put(claim, null); 225 } 226 } 227 228 return req; 229 } 230 231 232 /** 233 * Gets the claims request entries for this OpenID Connect scope value. 234 * 235 * <p>See OpenID Connect Core 1.0, section 5.1. 236 * 237 * @see #toClaimsSetRequestEntries() 238 * 239 * @return The claims request entries, {@code null} if not applicable 240 * (for scope values {@link #OPENID} and 241 * {@link #OFFLINE_ACCESS}). 242 */ 243 @Deprecated 244 public Set<ClaimsRequest.Entry> toClaimsRequestEntries() { 245 246 Set<ClaimsRequest.Entry> entries = new HashSet<>(); 247 248 if (this == OPENID || this == OFFLINE_ACCESS) 249 return Collections.unmodifiableSet(entries); 250 251 for (String claimName: getClaimNames()) 252 entries.add(new ClaimsRequest.Entry(claimName).withClaimRequirement(ClaimRequirement.VOLUNTARY)); 253 254 return Collections.unmodifiableSet(entries); 255 } 256 257 258 /** 259 * Gets the OpenID claims request entries for this OpenID Connect scope 260 * value. 261 * 262 * <p>See OpenID Connect Core 1.0, section 5.1. 263 * 264 * @return The OpenID claims request entries, {@code null} if not 265 * applicable (for scope values {@link #OPENID} and 266 * {@link #OFFLINE_ACCESS}). 267 */ 268 public List<ClaimsSetRequest.Entry> toClaimsSetRequestEntries() { 269 270 List<ClaimsSetRequest.Entry> entries = new LinkedList<>(); 271 272 if (this == OPENID || this == OFFLINE_ACCESS) 273 return Collections.unmodifiableList(entries); 274 275 for (String claimName: getClaimNames()) 276 entries.add(new ClaimsSetRequest.Entry(claimName).withClaimRequirement(ClaimRequirement.VOLUNTARY)); 277 278 return Collections.unmodifiableList(entries); 279 } 280}