Browse Source

database storage for device flow

pull/1161/merge
Justin Richer 8 years ago
parent
commit
44b24af466
  1. 15
      openid-connect-common/src/main/java/org/mitre/oauth2/model/DeviceCode.java
  2. 59
      openid-connect-common/src/main/java/org/mitre/oauth2/repository/impl/DeviceCodeRepository.java
  3. 2
      openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql
  4. 96
      openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaDeviceCodeRepository.java
  5. 48
      openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java
  6. 16
      openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java

15
openid-connect-common/src/main/java/org/mitre/oauth2/model/DeviceCode.java

@ -33,6 +33,8 @@ import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.MapKeyColumn;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.persistence.Temporal;
@ -42,8 +44,21 @@ import javax.persistence.Temporal;
*/
@Entity
@Table(name = "device_code")
@NamedQueries({
@NamedQuery(name = DeviceCode.QUERY_BY_USER_CODE, query = "select d from DeviceCode d where d.userCode = :" + DeviceCode.PARAM_USER_CODE),
@NamedQuery(name = DeviceCode.QUERY_BY_DEVICE_CODE, query = "select d from DeviceCode d where d.deviceCode = :" + DeviceCode.PARAM_DEVICE_CODE),
@NamedQuery(name = DeviceCode.QUERY_EXPIRED_BY_DATE, query = "select d from DeviceCode d where d.expiration <= :" + DeviceCode.PARAM_DATE)
})
public class DeviceCode {
public static final String QUERY_BY_USER_CODE = "DeviceCode.queryByUserCode";
public static final String QUERY_BY_DEVICE_CODE = "DeviceCode.queryByDeviceCode";
public static final String QUERY_EXPIRED_BY_DATE = "DeviceCode.queryExpiredByDate";
public static final String PARAM_USER_CODE = "userCode";
public static final String PARAM_DEVICE_CODE = "deviceCode";
public static final String PARAM_DATE = "date";
private Long id;
private String deviceCode;
private String userCode;

59
openid-connect-common/src/main/java/org/mitre/oauth2/repository/impl/DeviceCodeRepository.java

@ -0,0 +1,59 @@
/*******************************************************************************
* Copyright 2017 The MITRE Corporation
* and the MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
package org.mitre.oauth2.repository.impl;
import java.util.Set;
import org.mitre.oauth2.model.DeviceCode;
/**
* @author jricher
*
*/
public interface DeviceCodeRepository {
/**
* @param id
* @return
*/
public DeviceCode getById(Long id);
/**
* @param deviceCode
* @return
*/
public DeviceCode getByDeviceCode(String deviceCode);
/**
* @param scope
*/
public void remove(DeviceCode scope);
/**
* @param scope
* @return
*/
public DeviceCode save(DeviceCode scope);
/**
* @param userCode
* @return
*/
public DeviceCode getByUserCode(String userCode);
}

2
openid-connect-server-webapp/src/main/resources/db/hsql/hsql_database_tables.sql

@ -131,7 +131,7 @@ CREATE TABLE IF NOT EXISTS client_details (
dynamically_registered BOOLEAN DEFAULT false NOT NULL,
allow_introspection BOOLEAN DEFAULT false NOT NULL,
id_token_validity_seconds BIGINT DEFAULT 600 NOT NULL,
device_code_validity_seconds BIGINT DEFAULT 600 NOT NULL,
device_code_validity_seconds BIGINT,
client_id VARCHAR(256),
client_secret VARCHAR(2048),

96
openid-connect-server/src/main/java/org/mitre/oauth2/repository/impl/JpaDeviceCodeRepository.java

@ -0,0 +1,96 @@
/*******************************************************************************
* Copyright 2017 The MITRE Corporation
* and the MIT Internet Trust Consortium
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*******************************************************************************/
/**
*
*/
package org.mitre.oauth2.repository.impl;
import static org.mitre.util.jpa.JpaUtil.getSingleResult;
import static org.mitre.util.jpa.JpaUtil.saveOrUpdate;
import java.util.LinkedHashSet;
import java.util.Set;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import org.mitre.oauth2.model.DeviceCode;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;
/**
* @author jricher
*
*/
@Repository("jpaDeviceCodeRepository")
public class JpaDeviceCodeRepository implements DeviceCodeRepository {
@PersistenceContext(unitName="defaultPersistenceUnit")
private EntityManager em;
/* (non-Javadoc)
*/
@Override
@Transactional(value="defaultTransactionManager")
public DeviceCode getById(Long id) {
return em.find(DeviceCode.class, id);
}
/* (non-Javadoc)
*/
@Override
@Transactional(value="defaultTransactionManager")
public DeviceCode getByUserCode(String value) {
TypedQuery<DeviceCode> query = em.createNamedQuery(DeviceCode.QUERY_BY_USER_CODE, DeviceCode.class);
query.setParameter(DeviceCode.PARAM_USER_CODE, value);
return getSingleResult(query.getResultList());
}
/* (non-Javadoc)
*/
@Override
@Transactional(value="defaultTransactionManager")
public DeviceCode getByDeviceCode(String value) {
TypedQuery<DeviceCode> query = em.createNamedQuery(DeviceCode.QUERY_BY_DEVICE_CODE, DeviceCode.class);
query.setParameter(DeviceCode.PARAM_DEVICE_CODE, value);
return getSingleResult(query.getResultList());
}
/* (non-Javadoc)
*/
@Override
@Transactional(value="defaultTransactionManager")
public void remove(DeviceCode scope) {
DeviceCode found = getById(scope.getId());
if (found != null) {
em.remove(found);
}
}
/* (non-Javadoc)
* @see org.mitre.oauth2.repository.SystemScopeRepository#save(org.mitre.oauth2.model.SystemScope)
*/
@Override
@Transactional(value="defaultTransactionManager")
public DeviceCode save(DeviceCode scope) {
return saveOrUpdate(scope.getId(), em, scope);
}
}

48
openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/InMemoryDeviceCodeService.java → openid-connect-server/src/main/java/org/mitre/oauth2/service/impl/DefaultDeviceCodeService.java

@ -18,15 +18,15 @@
package org.mitre.oauth2.service.impl;
import java.util.Date;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import org.mitre.oauth2.model.AuthenticationHolderEntity;
import org.mitre.oauth2.model.ClientDetailsEntity;
import org.mitre.oauth2.model.DeviceCode;
import org.mitre.oauth2.repository.impl.DeviceCodeRepository;
import org.mitre.oauth2.service.DeviceCodeService;
import org.springframework.security.core.Authentication;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.provider.ClientDetails;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.stereotype.Service;
@ -35,10 +35,11 @@ import org.springframework.stereotype.Service;
* @author jricher
*
*/
@Service
public class InMemoryDeviceCodeService implements DeviceCodeService {
@Service("defaultDeviceCodeService")
public class DefaultDeviceCodeService implements DeviceCodeService {
private Set<DeviceCode> codes = new HashSet<>();
@Autowired
private DeviceCodeRepository repository;
/* (non-Javadoc)
* @see org.mitre.oauth2.service.DeviceCodeService#save(org.mitre.oauth2.model.DeviceCode)
@ -54,8 +55,7 @@ public class InMemoryDeviceCodeService implements DeviceCodeService {
dc.setApproved(false);
codes.add(dc);
return dc;
return repository.save(dc);
}
/* (non-Javadoc)
@ -63,12 +63,7 @@ public class InMemoryDeviceCodeService implements DeviceCodeService {
*/
@Override
public DeviceCode lookUpByUserCode(String userCode) {
for (DeviceCode dc : codes) {
if (dc.getUserCode().equals(userCode)) {
return dc;
}
}
return null;
return repository.getByUserCode(userCode);
}
/* (non-Javadoc)
@ -76,13 +71,16 @@ public class InMemoryDeviceCodeService implements DeviceCodeService {
*/
@Override
public DeviceCode approveDeviceCode(DeviceCode dc, OAuth2Authentication auth) {
dc.setApproved(true);
DeviceCode found = repository.getById(dc.getId());
found.setApproved(true);
AuthenticationHolderEntity authHolder = new AuthenticationHolderEntity();
authHolder.setAuthentication(auth);
dc.setAuthenticationHolder(authHolder);
found.setAuthenticationHolder(authHolder);
return dc;
return repository.save(found);
}
/* (non-Javadoc)
@ -90,13 +88,19 @@ public class InMemoryDeviceCodeService implements DeviceCodeService {
*/
@Override
public DeviceCode consumeDeviceCode(String deviceCode, ClientDetails client) {
for (DeviceCode dc : codes) {
if (dc.getDeviceCode().equals(deviceCode) && dc.getClientId().equals(client.getClientId())) {
codes.remove(dc);
return dc;
}
DeviceCode found = repository.getByDeviceCode(deviceCode);
// make sure it's not used twice
repository.remove(found);
if (found.getClientId().equals(client.getClientId())) {
// make sure the client matches, if so, we're good
return found;
} else {
// if the clients don't match, pretend the code wasn't found
return null;
}
return null;
}
}

16
openid-connect-server/src/main/java/org/mitre/oauth2/web/DeviceEndpoint.java

@ -19,6 +19,7 @@ package org.mitre.oauth2.web;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
@ -147,12 +148,15 @@ public class DeviceEndpoint {
DeviceCode dc = deviceCodeService.createNewDeviceCode(deviceCode, userCode, requestedScopes, client, parameters);
model.put(JsonEntityView.ENTITY, ImmutableMap.of(
"device_code", deviceCode,
"user_code", userCode,
"verification_uri", config.getIssuer() + URL,
"expires_in", client.getDeviceCodeValiditySeconds()
));
Map<String, Object> response = new HashMap<>();
response.put("device_code", deviceCode);
response.put("user_code", userCode);
response.put("verification_uri", config.getIssuer() + USER_URL);
if (client.getDeviceCodeValiditySeconds() != null) {
response.put("expires_in", client.getDeviceCodeValiditySeconds());
}
model.put(JsonEntityView.ENTITY, response);
return JsonEntityView.VIEWNAME;

Loading…
Cancel
Save