Device Consent Page "Cancel" still logs in the user
Describe the bug Once I've granted access to a client id via device authorization grant to one device, any furthur devices using the same client id will still be approved even when the consent page is canceled.
To Reproduce Steps to reproduce the behavior.
- Trigger a device authentication with client=123
- When prompted for Device Consent,
- Specify the granted scopes and click "Approve"
- Trigger a device authentication with client=123 but on a new device.
- When prompted for Device Consent, the specified granted scope is greyed out, but both Buttons "Approve" and Cancel" appear. Click "Cancel"
- The second device still gets an access token
Expected behavior I was hoping that the second device would get a "access_denied"
I demoed this behavior to @jgrandja at spring one yesterday. Thanks Joe
Workaround I've been able to get my acceptance tests to get the correct behavior, so I believe that with a custom consent page I can get the behavior expected by setting an empty scope parameter.
I'm realizing that the real issue here is that the consent page is even presented a second time when the consent was saved the first time.
I'm thinking I'd like to selectivly configure which clients I even want to bother saving off the consent. For a roku type device I think we'd prefer not saving the consent. It appears that there already exists an isRequireAuthorizationConsent that doesn't seem to do what I'm interpreting it to mean.
The following work-around gets the behavior I'm after but it seems like a bit of a hack. It bypasses saving the consent if the client is configured with isRequireAuthorizationConsent.
Something like this:
public class BypassAuthorizationConsentService implements OAuth2AuthorizationConsentService {
final OAuth2AuthorizationConsentService authorizationConsentService;
final RegisteredClientRepository registeredClientRepository;
public BypassAuthorizationConsentService(OAuth2AuthorizationConsentService authorizationConsentService,
RegisteredClientRepository registeredClientRepository) {
this.authorizationConsentService = authorizationConsentService;
this.registeredClientRepository = registeredClientRepository;
}
@Override
public void save(OAuth2AuthorizationConsent authorizationConsent) {
RegisteredClient client = registeredClientRepository.findByClientId(authorizationConsent.getRegisteredClientId());
if (client.getClientSettings().isRequireAuthorizationConsent()) {
// Don't save consent for this client
return;
}
authorizationConsentService.save(authorizationConsent);
}
@Override
public void remove(OAuth2AuthorizationConsent authorizationConsent) {
authorizationConsentService.remove(authorizationConsent);
}
@Override
public OAuth2AuthorizationConsent findById(String registeredClientId, String principalName) {
return authorizationConsentService.findById(registeredClientId, principalName);
}
}
And setup the bean like this:
@Bean
public OAuth2AuthorizationConsentService authorizationConsentService(JdbcTemplate jdbcTemplate,
RegisteredClientRepository registeredClientRepository) {
return new DeviceBypassAuthorizationConsentService(
new JdbcOAuth2AuthorizationConsentService(jdbcTemplate, registeredClientRepository),
registeredClientRepository);
}
One more realization. The current consent page has two distinct functions:
- Scope consent, which only has to happen once
- User and User-code verification:
- Is the user correct? (opps, my spouse is logged in.. cancel)
- Is the user code correct? "Verify that this code matches what is shown on the device"
I realize now that number 2 is what I'm after.
@c-a-m Apologies for the delay. I'm currently working on a high priority task and should have it completed by early next week, at which point I will take a look at this issue. Thanks for your patience.
@c-a-m I was not able to reproduce the flow as described in the main comment.
- When prompted for Device Consent, the specified granted scope is greyed out, but both Buttons "Approve" and Cancel" appear. Click "Cancel"
I used the Demo Sample to try to reproduce. The first time around I consent message.read and message.write to device-messaging-client and complete the flow. The 2nd time around, I perform the exact same flow but the consent page is not presented because message.read and message.write was previously consented to device-messaging-client, which is the behaviour I expect.
I'm realizing that the real issue here is that the consent page is even presented a second time when the consent was saved the first time.
Can you try the demo sample yourself and perform the same flow and let me know if you're able to reproduce it with the sample.
I'm guessing your application setup has some custom configurations which is not behaving the same as the demo sample. The consent page is not presented the 2nd time around in the demo sample.
If you would like us to look at this issue, please provide the requested information. If the information is not provided within the next 7 days this issue will be closed.
Closing due to lack of requested feedback. If you would like us to look at this issue, please provide the requested information and we will re-open the issue.