IdentityServer doesn't work with OAuth2 and its probably Open ID's fault!
I am really excited to be working with Dominick Baier of IdentityServer next week to help PixelPin implement OpenID Connect using the IdentityServer library. We already have a (homemade) OAuth2 solution but OpenID Connect has some more complexity which i didn't particularly want to hack around with myself, especially since the number of test cases goes up exponentially with every option, grant type, response mode etc.
In fact, I have already got the openid connect login working and have been testing it with a wordpress oauth2 plugin. I realised it doesn't work even though openid is supposed to be a superset of OAuth2 and IdentityServer is supposed to work with OAuth2.
My first problem was that "scope" is required by IdentityServer and is required by OpenID Connect but it is NOT required by OAuth2 and not all plugins will pass scope, since OAuth2 allows an IdP to have a default scope if not passed. Whether or not that was a good idea, it is what RFC6749 allows and it should be permitted. I had a discussion on Github with Brock Allen, the other main author of IdentityServer and he didn't seem to understand what I was saying and why it was broken. Since OAuth2 allows a default scope, I offered to create a Pull Request that allows the user to specify a default and only to error if the default is not set AND scope is not passed but Brock didn't agree. I have already modified my copy of IdentityServer to not require scope.
The second problem is that AuthorizeRequestValidator has some sloppy (in my opinion) logic when checking the request. It basically says, "if there are any openid scopes but one of the scopes is not openid, throw an error". The problem is that this assumes that openid scopes are unique to openid and that is not true. Many OAuth2 providers will use a scope called email in a non-openid request and this does not indicate that it is an incorrect openid request, just that it is not openid. I am going to raise this on Github and see what happens!
Anyway, it raises another issue in what happens when you create something like OpenID Connect to "sit on top of" OAuth2 and where the specs conflict. OpenID Connect basically says that the userdata endpoint should use Bearer Token authentication whereas OAuth2 is not specific. What does that mean for implementers? IdentityServer is clearly very much OpenID oriented and requires the userdata request to be Bearer Token whereas my OAuth2 plugin simply provides it as a POST body param, which is also allowed in certain specific scenarios but which is not guaranteed to be supported by OpenID resource servers.
For me, the key should be the openid scope. If it is NOT present then the system should behave in the same way as any normal OAuth2 provider - something that IdentityServer does NOT do. If openid is a requested scope, then the system can go to town on validation and error messages since it is now in the secure world of open id connect.
OpenID Connect is gaining ground but there are still many OAuth2 clients that don't support openid connect and possibly won't work with IdentityServer, at least without some changes to them which might or might be possible.
Anyway, hopefully, Dominick will put me straight! Until then, you have been warned.
In fact, I have already got the openid connect login working and have been testing it with a wordpress oauth2 plugin. I realised it doesn't work even though openid is supposed to be a superset of OAuth2 and IdentityServer is supposed to work with OAuth2.
My first problem was that "scope" is required by IdentityServer and is required by OpenID Connect but it is NOT required by OAuth2 and not all plugins will pass scope, since OAuth2 allows an IdP to have a default scope if not passed. Whether or not that was a good idea, it is what RFC6749 allows and it should be permitted. I had a discussion on Github with Brock Allen, the other main author of IdentityServer and he didn't seem to understand what I was saying and why it was broken. Since OAuth2 allows a default scope, I offered to create a Pull Request that allows the user to specify a default and only to error if the default is not set AND scope is not passed but Brock didn't agree. I have already modified my copy of IdentityServer to not require scope.
The second problem is that AuthorizeRequestValidator has some sloppy (in my opinion) logic when checking the request. It basically says, "if there are any openid scopes but one of the scopes is not openid, throw an error". The problem is that this assumes that openid scopes are unique to openid and that is not true. Many OAuth2 providers will use a scope called email in a non-openid request and this does not indicate that it is an incorrect openid request, just that it is not openid. I am going to raise this on Github and see what happens!
Anyway, it raises another issue in what happens when you create something like OpenID Connect to "sit on top of" OAuth2 and where the specs conflict. OpenID Connect basically says that the userdata endpoint should use Bearer Token authentication whereas OAuth2 is not specific. What does that mean for implementers? IdentityServer is clearly very much OpenID oriented and requires the userdata request to be Bearer Token whereas my OAuth2 plugin simply provides it as a POST body param, which is also allowed in certain specific scenarios but which is not guaranteed to be supported by OpenID resource servers.
For me, the key should be the openid scope. If it is NOT present then the system should behave in the same way as any normal OAuth2 provider - something that IdentityServer does NOT do. If openid is a requested scope, then the system can go to town on validation and error messages since it is now in the secure world of open id connect.
OpenID Connect is gaining ground but there are still many OAuth2 clients that don't support openid connect and possibly won't work with IdentityServer, at least without some changes to them which might or might be possible.
Anyway, hopefully, Dominick will put me straight! Until then, you have been warned.