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.oauth2.sdk; 019 020 021import java.util.*; 022 023import net.jcip.annotations.Immutable; 024import net.jcip.annotations.NotThreadSafe; 025 026import com.nimbusds.oauth2.sdk.id.Identifier; 027 028 029/** 030 * Authorisation scope. 031 * 032 * <p>Example scope from OpenID Connect indicating access to the user's email 033 * and profile details: 034 * 035 * <pre> 036 * Scope scope = new Scope(); 037 * scope.add(OIDCScopeValue.OPENID); 038 * scope.add(OIDCScopeValue.EMAIL); 039 * scope.add(OIDCScopeValue.PROFILE); 040 * </pre> 041 * 042 * <p>Related specifications: 043 * 044 * <ul> 045 * <li>OAuth 2.0 (RFC 6749) 046 * </ul> 047 */ 048@NotThreadSafe 049public class Scope extends LinkedHashSet<Scope.Value> { 050 051 052 private static final long serialVersionUID = -553103514038936007L; 053 054 055 /** 056 * Authorisation scope value. 057 */ 058 @Immutable 059 public static class Value extends Identifier { 060 061 062 private static final long serialVersionUID = -1885648673808651565L; 063 064 065 /** 066 * Enumeration of the scope value requirements for 067 * application-specific authorisation requests. 068 */ 069 public enum Requirement { 070 071 072 /** 073 * The value must be present in the {@link Scope} 074 * parameter. 075 */ 076 REQUIRED, 077 078 079 /** 080 * The value may be optionally included in the 081 * {@link Scope} parameter. 082 */ 083 OPTIONAL 084 } 085 086 087 /** 088 * Optional requirement. 089 */ 090 private final Value.Requirement requirement; 091 092 093 /** 094 * Creates a new scope value. The requirement is not specified. 095 * 096 * @param value The scope value. Must not be {@code null} or 097 * empty string. 098 */ 099 public Value(final String value) { 100 101 this(value, null); 102 } 103 104 /** 105 * Creates a new scope value with an optional requirement. 106 * 107 * @param value The scope value. Must not be {@code null} 108 * or empty string. 109 * @param requirement The requirement, {@code null} if not 110 * specified. 111 */ 112 public Value(final String value, final Requirement requirement) { 113 114 super(value); 115 116 this.requirement = requirement; 117 } 118 119 120 /** 121 * Gets the requirement of this scope value. 122 * 123 * @return The requirement, {@code null} if not specified. 124 */ 125 public Requirement getRequirement() { 126 127 return requirement; 128 } 129 130 131 @Override 132 public boolean equals(final Object object) { 133 134 return object instanceof Value && 135 this.toString().equals(object.toString()); 136 } 137 } 138 139 140 /** 141 * Creates a new empty authorisation scope. 142 */ 143 public Scope() { 144 // Nothing to do 145 } 146 147 148 /** 149 * Creates a new scope from the specified scope. 150 * 151 * @param scope The scope. May be {@code null}. 152 */ 153 public Scope(final Scope scope) { 154 155 if (scope == null) { 156 return; 157 } 158 159 addAll(scope); 160 } 161 162 163 /** 164 * Creates a new authorisation scope with the specified string values. 165 * 166 * @param values The string values. 167 */ 168 public Scope(final String ... values) { 169 170 for (String v: values) 171 add(new Value(v)); 172 } 173 174 175 /** 176 * Creates a new authorisation scope with the specified values. 177 * 178 * @param values The values. 179 */ 180 public Scope(final Value ... values) { 181 182 addAll(Arrays.asList(values)); 183 } 184 185 186 /** 187 * Adds the specified string value to this scope. 188 * 189 * @param value The string value. Must not be {@code null}. 190 * 191 * @return {@code true} if this scope did not already contain the 192 * specified value. 193 */ 194 public boolean add(final String value) { 195 196 return add(new Value(value)); 197 } 198 199 200 /** 201 * Checks if this scope contains the specified string value. 202 * 203 * @param value The string value. Must not be {@code null}. 204 * 205 * @return {@code true} if the value is contained, else {@code false}. 206 */ 207 public boolean contains(final String value) { 208 209 return contains(new Value(value)); 210 } 211 212 213 /** 214 * Returns the string representation of this scope. The scope values 215 * will be serialised in the order they were added. 216 * 217 * @return The string representation. 218 */ 219 @Override 220 public String toString() { 221 222 StringBuilder sb = new StringBuilder(); 223 224 for (Scope.Value v : this) { 225 226 if (sb.length() > 0) { 227 sb.append(' '); 228 } 229 230 sb.append(v.toString()); 231 } 232 233 return sb.toString(); 234 } 235 236 237 /** 238 * Returns the string list representation of this scope. The scope 239 * values will be serialised in the order they were added. 240 * 241 * @return The string list representation. 242 */ 243 public List<String> toStringList() { 244 245 List<String> list = new ArrayList<>(this.size()); 246 247 for (Scope.Value v: this) 248 list.add(v.getValue()); 249 250 return list; 251 } 252 253 254 /** 255 * Parses a scope from the specified string collection representation. 256 * 257 * @param collection The string collection, {@code null} if not 258 * specified. 259 * 260 * @return The scope, {@code null} if not specified. 261 */ 262 public static Scope parse(final Collection<String> collection) { 263 264 if (collection == null) 265 return null; 266 267 Scope scope = new Scope(); 268 269 for (String v: collection) 270 scope.add(new Scope.Value(v)); 271 272 return scope; 273 } 274 275 276 /** 277 * Parses a scope from the specified string representation. 278 * 279 * @param s The scope string, {@code null} if not specified. 280 * 281 * @return The scope, {@code null} if not specified. 282 */ 283 public static Scope parse(final String s) { 284 285 if (s == null) 286 return null; 287 288 Scope scope = new Scope(); 289 290 if (s.trim().isEmpty()) 291 return scope; 292 293 StringTokenizer st = new StringTokenizer(s, " "); 294 295 while(st.hasMoreTokens()) 296 scope.add(new Scope.Value(st.nextToken())); 297 298 return scope; 299 } 300}