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.device; 019 020 021import com.nimbusds.oauth2.sdk.AuthorizationGrant; 022import com.nimbusds.oauth2.sdk.GrantType; 023import com.nimbusds.oauth2.sdk.OAuth2Error; 024import com.nimbusds.oauth2.sdk.ParseException; 025import com.nimbusds.oauth2.sdk.util.MultivaluedMapUtils; 026import net.jcip.annotations.Immutable; 027 028import java.util.*; 029 030 031/** 032 * Device code grant for the OAuth 2.0 Device Authorization Grant. 033 * 034 * <p>Related specifications: 035 * 036 * <ul> 037 * <li>OAuth 2.0 Device Authorization Grant (RFC 8628) 038 * </ul> 039 */ 040@Immutable 041public class DeviceCodeGrant extends AuthorizationGrant { 042 043 044 /** 045 * The grant type. 046 */ 047 public static final GrantType GRANT_TYPE = GrantType.DEVICE_CODE; 048 049 050 /** 051 * The device code received from the authorisation server. 052 */ 053 private final DeviceCode deviceCode; 054 055 056 /** 057 * Creates a new device code grant. 058 * 059 * @param deviceCode The device code. Must not be {@code null}. 060 */ 061 public DeviceCodeGrant(final DeviceCode deviceCode) { 062 063 super(GRANT_TYPE); 064 this.deviceCode = Objects.requireNonNull(deviceCode); 065 } 066 067 068 /** 069 * Returns the device code received from the authorisation server. 070 * 071 * @return The device code received from the authorisation server. 072 */ 073 public DeviceCode getDeviceCode() { 074 075 return deviceCode; 076 } 077 078 079 @Override 080 public Map<String, List<String>> toParameters() { 081 082 Map<String, List<String>> params = new LinkedHashMap<>(); 083 params.put("grant_type", Collections.singletonList(GRANT_TYPE.getValue())); 084 params.put("device_code", Collections.singletonList(deviceCode.getValue())); 085 return params; 086 } 087 088 089 /** 090 * Parses a device code grant from the specified request body 091 * parameters. 092 * 093 * <p>Example: 094 * 095 * <pre> 096 * grant_type=urn%3Aietf%3Aparams%3Aoauth%3Agrant-type%3Adevice_code 097 * &device_code=GmRhmhcxhwAzkoEqiMEg_DnyEysNkuNhszIySk9eS 098 * </pre> 099 * 100 * @param params The parameters. 101 * 102 * @return The device code grant. 103 * 104 * @throws ParseException If parsing failed. 105 */ 106 public static DeviceCodeGrant parse(final Map<String, List<String>> params) throws ParseException { 107 108 GrantType.ensure(GRANT_TYPE, params); 109 110 String deviceCodeString = MultivaluedMapUtils.getFirstValue(params, "device_code"); 111 112 if (deviceCodeString == null || deviceCodeString.trim().isEmpty()) { 113 String msg = "Missing or empty device_code parameter"; 114 throw new ParseException(msg, OAuth2Error.INVALID_REQUEST.appendDescription(": " + msg)); 115 } 116 117 DeviceCode deviceCode = new DeviceCode(deviceCodeString); 118 119 return new DeviceCodeGrant(deviceCode); 120 } 121 122 123 @Override 124 public boolean equals(Object o) { 125 126 if (this == o) 127 return true; 128 if (!(o instanceof DeviceCodeGrant)) 129 return false; 130 131 DeviceCodeGrant deviceCodeGrant = (DeviceCodeGrant) o; 132 return deviceCode.equals(deviceCodeGrant.deviceCode); 133 } 134 135 136 @Override 137 public int hashCode() { 138 139 return deviceCode.hashCode(); 140 } 141}