In this post, I write about my first experience with developing an app that implements an integration between BC and an external API. If you’re like me, most of the web services stuff goes straight over your head. Sure, with some sample code and following along with demos in a class, I can get it to work. BUT… just ONE itsy bitsy teeny weeny tiny thingy goes wrong and you’re absolutely dead in the water. Thankfully I have friends who are willing to help, and I want to pass on this knowledge so others don’t have to spend days trying to figure this out.
The Flow Itself
The “Authorization Code Grant Flow” is just one of several OAuth flows, and one of the first to be implemented. Go here if you want to read more technical details, but if this is the first time you’re reading about this I can guarantee you that you will not understand any of it, I know I didn’t 🙂
As with all OAuth flows, to get access to the actual API you must first get an access token. The thing that makes the authorization code grant flow stand out from other OAuth flows is:
- There is an additional token that you must get before requesting the access token, this token is called the ‘Authorization Code’
- In order to get this authorization code, a human being must enter the credentials. This flow is specifically designed NOT to provide any automated way to get the tokens
The MOST confusing thing is that although there is supposed to be an industry standard for REST APIs, it seems that each one has a slightly different way of connecting. One API that I worked on, for instance, had yet another token that is used for the API itself. As if this stuff isn’t hard enough to understand, some of them make it even more difficult. Most of them make an honest effort to provide really good documentation and in some cases even support forums.
The essential flow requires three things:
- API Credentials. You get these by signing up with the API provider, and they usually consist of a login ID and a ‘secret’, sometimes an additional password. They are meant to authenticate a human being logging into the API
- Authorization Code. This code is used to request the ‘Access Token’ that is used to get access to the API itself
- Access/Refresh Token. This is usually a set of two tokens. The Access Token is used for access to the API, and it usually has an expiration date/time. The Refresh Token is used to get a fresh Access Token. As long as you have a valid Refresh Token, you will not need to log back into the API
Each API that implements the authorization code grant flow will provide an endpoint for the authorization code, as well as an endpoint for the access and refresh tokens. You’d be surprised at how many ways this “standard” flow can be implemented though, so you’ll have to find the details yourself. Just hope that the API provider has good documentation.
Log In for the Authorization Code
You get credentials from the API provider, usually in the form of an ID and a ‘Secret’, sometimes with an additional password. For the authorization code grant flow, a human being is required to enter those credentials to authenticate the connection. In BC, the only way to get past this stage is by using a standard control add-in called ‘OAuthControlAddIn’. I’ve written another post that explains the details.
The control add-in provides the mechanics behind the login and processing the redirect response that comes back from the authorization endpoint, and it passes the authorization code itself back to AL through an event in the control add-in. You then take this authorization code and pass that to the token endpoint for the final piece.
Request The Access/Refresh Token
The token endpoint is the final step of the authentication process of the Authorization Code Grant Flow. Sometimes there is a separate endpoint for new tokens and another one for refreshing tokens. Other APIs have a single endpoint with two modes. One accepts the authorization code, the other accepts a refresh token, and they both return a new token pair.
The API checks the validity of the refresh token in every single API call. It is up to you to make sure that your token is valid, and the API usually provides a straightforward way for you to keep track of this yourself, by for instance providing the expiration date/time as part of the token response.
Keep Your Tokens Fresh
The Access Token usually has an expiration date/time. Some tokens are valid for a short period like 10 minutes, others have a longer shelf life. It is up to you to develop logic that checks the validity of your current tokens, and to request new tokens when they expire.
As long as your tokens are valid, you should not have to re-enter credentials, and there is no need for a new Authorization Code. The authorization code is only used when authenticating a fresh connection to the API. Once you’re past the authorization code stage, you should be able to keep the tokens fresh without having a human being log back in.
In AL, the most common way to store the tokens is through the isolated storage functionality. You can set the scope of isolated storage for the whole company, so that multiple users can share the API connection.
My Difficult Experience
One of the reasons why my experience was so difficult was the fact that the API that I was working with had a third token called ‘RestToken’. At the time, I was barely understanding these codes and tokens, and then there was this other token that I could not find in the excellent training that I had followed. Lucky for me, I had some help and was able to understand what was causing the confusion.
My guess (and it really is only a guess) why this is the case is that the API was initially developed with just this ‘RestToken’ and that at some point they built a wrapper around the API to comply with the OAuth “standard”.
The point is that each API has its own unique attributes, and its own way of implementing something that is supposed to be “standard”. Slowly but surely I started seeing the elements of what makes the flow work, and had an excellent teacher who showed me a solid way to handle that in AL code. Normally I would share the code in these posts. At the moment though I only have the training material and the client production code, neither one is mine to share. Maybe in the future when I’m less busy I’ll take some time to put some code together.
Let me know if this helps or not, I’d be happy to get your feedback and try to help if you need some.