├── .gitignore ├── LICENSE ├── README.md ├── client.go ├── common.go ├── deactivate_account.go ├── examples ├── client.go ├── deactivate_account.go ├── forgot_password.go ├── get_meta_data.go ├── get_profile.go ├── get_session.go ├── login.go ├── logout.go ├── magic_link_login.go ├── resend_otp.go ├── reset_password.go ├── revoke_token.go ├── signup.go ├── update_profile.go ├── validate_jwt_token.go ├── validate_session.go ├── verify_email.go └── verify_otp.go ├── forgot_password.go ├── get_meta_data.go ├── get_profile.go ├── get_session.go ├── get_token.go ├── go.mod ├── graphql.go ├── login.go ├── logout.go ├── magic_link_login.go ├── resend_otp.go ├── reset_password.go ├── revoke_token.go ├── signup.go ├── test └── main.go ├── update_profile.go ├── utils.go ├── validate_jwt_token.go ├── validate_session.go ├── verify_email.go └── verify_otp.go /.gitignore: -------------------------------------------------------------------------------- 1 | # Binaries for programs and plugins 2 | *.exe 3 | *.exe~ 4 | *.dll 5 | *.so 6 | *.dylib 7 | 8 | # Test binary, built with `go test -c` 9 | *.test 10 | 11 | # Output of the go coverage tool, specifically when used with LiteIDE 12 | *.out 13 | 14 | # Dependency directories (remove the comment below to include it) 15 | # vendor/ 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 authorizer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # authorizer-go 2 | 3 | Golang SDK for [authorizer.dev](https://authorizer.dev) server. This SDK will be handy to add API middleware where you can authorize your users. It will also empower you to perform various auth operations on authorizer server. 4 | 5 | For detailed explanation of each functions check official [docs](https://pkg.go.dev/github.com/authorizerdev/authorizer-go) 6 | 7 | ## Getting Started 8 | 9 | **Pre-requisite**: You will need an authorizer instance up and running. Checkout how you can host your instance in the [docs](https://docs.authorizer.dev/deployment) 10 | 11 | Follow the steps here to install authorizer-go in your golang project and use the methods of SDK to protect/authorize your APIs 12 | 13 | Once you have deployed authorizer instance. Get `Client ID` from your authorizer instance dashboard 14 | 15 | ![client_id](https://res.cloudinary.com/dcfpom7fo/image/upload/v1663437088/Authorizer/client_id_ptjsvc.png) 16 | 17 | ### Step 1: Install authorizer-go SDK 18 | 19 | Run the following command to download authorizer-go SDK 20 | 21 | ```bash 22 | go get github.com/authorizerdev/authorizer-go 23 | ``` 24 | 25 | ### Step 2: Initialize authorizer client 26 | 27 | **Parameters** 28 | 29 | | Key | Type | Required | Description | 30 | | --------------- | ------------------- | -------------------- | --------------------------------------------------------------------------------------------------------------- | 31 | | `clientID` | `string` | `true` | Your unique client identifier obtained from authorizer dashboard | 32 | | `authorizerURL` | `string` | `true` | Authorizer server URL | 33 | | `redirectURL` | `string` | `false` | Default URL to which you would like to redirect the user in case of successful signup / login / forgot password | 34 | | `extraHeaders` | `map[string]string` | `false` | set of headers that you would like to pass with each request | 35 | 36 | **Example** 37 | 38 | ```go 39 | defaultHeaders := map[string]string{} 40 | 41 | authorizerClient, err := authorizer.NewAuthorizerClient("YOUR_CLIENT_ID", "YOUR_AUHTORIZER_URL", "OPTIONAL_REDIRECT_URL", defaultHeaders) 42 | if err != nil { 43 | panic(err) 44 | } 45 | ``` 46 | 47 | ### Step 3: Access all the SDK methods using authorizer client instance, initialized on step 2 48 | 49 | **Example** 50 | 51 | ```go 52 | response, err := authorizerClient.Login(&authorizer.LoginInput{ 53 | Email: "test@yopmail.com", 54 | Password: "Abc@123", 55 | }) 56 | if err != nil { 57 | panic(err) 58 | } 59 | ``` 60 | 61 | ## How to use authorizer as API gateway 62 | 63 | > Note: This example demonstrates how to use authorizer in middleware for a [go-gin](https://github.com/gin-gonic/gin) server. But logic remains the same under the hood, where you can get auth token from `header` and validate it via authorizer SDK 64 | 65 | ```go 66 | package main 67 | 68 | import ( 69 | "net/http" 70 | "strings" 71 | 72 | "github.com/authorizerdev/authorizer-go" 73 | "github.com/gin-gonic/gin" 74 | ) 75 | 76 | func AuthorizeMiddleware() gin.HandlerFunc { 77 | return func(c *gin.Context) { 78 | /** 79 | for open routes you can add condition here and just return with c.Next() 80 | so that it does not validate token for those routes 81 | */ 82 | 83 | authHeader := c.Request.Header.Get("Authorization") 84 | tokenSplit := strings.Split(authHeader, " ") 85 | 86 | defaultHeaders := map[string]string{} 87 | authorizerClient, err := authorizer.NewAuthorizerClient("YOUR_CLIENT_ID", "YOUR_AUHTORIZER_URL", "OPTIONAL_REDIRECT_URL", defaultHeaders) 88 | if err != nil { 89 | // unauthorized 90 | c.AbortWithStatusJSON(401, "unauthorized") 91 | return 92 | } 93 | 94 | if len(tokenSplit) < 2 || tokenSplit[1] == "" { 95 | // unauthorized 96 | c.AbortWithStatusJSON(401, "unauthorized") 97 | return 98 | } 99 | 100 | res, err := authorizerClient.ValidateJWTToken(&authorizer.ValidateJWTTokenInput{ 101 | TokenType: authorizer.TokenTypeIDToken, 102 | Token: tokenSplit[1], 103 | }) 104 | if err != nil { 105 | // unauthorized 106 | c.AbortWithStatusJSON(401, "unauthorized") 107 | return 108 | } 109 | 110 | if !res.IsValid { 111 | // unauthorized 112 | c.AbortWithStatusJSON(401, "unauthorized") 113 | return 114 | } 115 | 116 | c.Next() 117 | } 118 | } 119 | 120 | func main() { 121 | router := gin.New() 122 | router.Use(AuthorizeMiddleware()) 123 | 124 | router.GET("/ping", func(c *gin.Context) { 125 | c.JSON(http.StatusOK, gin.H{ 126 | "message": "pong", 127 | }) 128 | }) 129 | 130 | router.Run(":8090") 131 | } 132 | ``` 133 | 134 | 135 | **CURL command to test go-gin server created in example** 136 | 137 | Copy JWT ID token from login response of authorizer `login` mutation / social media login and replace `JWT_TOKEN` below 138 | 139 | ```bash 140 | curl --location --request GET 'http://localhost:8090/ping' \ 141 | --header 'Authorization: Bearer JWT_TOKEN' 142 | ``` -------------------------------------------------------------------------------- /client.go: -------------------------------------------------------------------------------- 1 | // Package authorizer provides client and methods using which you can 2 | // perform various graphql operations to your authorizer instance 3 | package authorizer 4 | 5 | import ( 6 | "fmt" 7 | "strings" 8 | ) 9 | 10 | // AuthorizerClient defines the attributes required to initiate authorizer client 11 | type AuthorizerClient struct { 12 | ClientID string 13 | AuthorizerURL string 14 | RedirectURL string 15 | ExtraHeaders map[string]string 16 | } 17 | 18 | // NewAuthorizerClient creates an authorizer client instance. 19 | // It returns reference to authorizer client instance or error. 20 | func NewAuthorizerClient(clientID, authorizerURL, redirectURL string, extraHeaders map[string]string) (*AuthorizerClient, error) { 21 | if strings.TrimSpace(clientID) == "" { 22 | return nil, fmt.Errorf("clientID missing") 23 | } 24 | 25 | if strings.TrimSpace(authorizerURL) == "" { 26 | return nil, fmt.Errorf("authorizerURL missing") 27 | } 28 | 29 | // extraHeaders is optional parameter, 30 | // hence if not set, initialize it with empty map 31 | headers := extraHeaders 32 | if headers == nil { 33 | headers = make(map[string]string) 34 | } 35 | 36 | // if x-authorizer-url is not present 37 | // set it to authorizerURL 38 | if _, ok := headers["x-authorizer-url"]; !ok { 39 | headers["x-authorizer-url"] = authorizerURL 40 | } 41 | 42 | // Add clientID to headers 43 | headers["x-authorizer-client-id"] = clientID 44 | 45 | return &AuthorizerClient{ 46 | RedirectURL: strings.TrimSuffix(redirectURL, "/"), 47 | AuthorizerURL: strings.TrimSuffix(authorizerURL, "/"), 48 | ClientID: clientID, 49 | ExtraHeaders: extraHeaders, 50 | }, nil 51 | } 52 | -------------------------------------------------------------------------------- /common.go: -------------------------------------------------------------------------------- 1 | package authorizer 2 | 3 | import "fmt" 4 | 5 | const ( 6 | // GrantTypeAuthorizationCode is used for authorization_code grant type 7 | GrantTypeAuthorizationCode = "authorization_code" 8 | 9 | // GrantTypeRefreshToken is used for refresh_token grant type 10 | GrantTypeRefreshToken = "refresh_token" 11 | 12 | // UserFragment defines graphql fragment for all the user attributes 13 | UserFragment = `id email email_verified given_name family_name middle_name nickname preferred_username picture signup_methods gender birthdate phone_number phone_number_verified roles created_at updated_at is_multi_factor_auth_enabled app_data 14 | ` 15 | ) 16 | 17 | // AuthTokenResponseFragment defines graphql response for auth token type, 18 | // which is common across various authorizer operations 19 | var AuthTokenResponseFragment = fmt.Sprintf(`message access_token expires_in refresh_token id_token should_show_email_otp_screen should_show_mobile_otp_screen user { %s }`, UserFragment) 20 | 21 | // User defines attributes for user instance 22 | type User struct { 23 | ID string `json:"id"` 24 | Email string `json:"email"` 25 | PreferredUsername string `json:"preferred_username"` 26 | EmailVerified bool `json:"email_verified"` 27 | SignupMethods string `json:"signup_methods"` 28 | GivenName *string `json:"given_name"` 29 | FamilyName *string `json:"family_name"` 30 | MiddleName *string `json:"middle_name"` 31 | Nickname *string `json:"nickname"` 32 | Picture *string `json:"picture"` 33 | Gender *string `json:"gender"` 34 | Birthdate *string `json:"birthdate"` 35 | PhoneNumber *string `json:"phone_number"` 36 | PhoneNumberVerified *bool `json:"phone_number_verified"` 37 | Roles []*string `json:"roles"` 38 | CreatedAt int64 `json:"created_at"` 39 | UpdatedAt int64 `json:"updated_at"` 40 | IsMultiFactorAuthEnabled *bool `json:"is_multi_factor_auth_enabled"` 41 | AppData map[string]interface{} `json:"app_data,omitempty"` 42 | } 43 | 44 | // AuthTokenResponse defines attribute for auth token response, 45 | // which is common across various authorizer operations 46 | type AuthTokenResponse struct { 47 | Message *string `json:"message,omitempty"` 48 | AccessToken *string `json:"access_token,omitempty"` 49 | ExpiresIn *int64 `json:"expires_in,omitempty"` 50 | IdToken *string `json:"id_token,omitempty"` 51 | RefreshToken *string `json:"refresh_token,omitempty"` 52 | ShouldShowEmailOtpScreen *bool `json:"should_show_email_otp_screen"` 53 | ShouldShowMobileOtpScreen *bool `json:"should_show_mobile_otp_screen"` 54 | User *User `json:"user,omitempty"` 55 | } 56 | 57 | // Response defines attribute for Response graphql type 58 | // it is common across various authorizer operations 59 | type Response struct { 60 | Message string `json:"message"` 61 | } 62 | -------------------------------------------------------------------------------- /deactivate_account.go: -------------------------------------------------------------------------------- 1 | package authorizer 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | // DeactivateAccount is method attached to AuthorizerClient. 8 | // It performs deactivate_account mutation on authorizer instance. 9 | // It returns Response reference or error. 10 | // For implementation details check DeactivateAccountExample examples/deactivate_account.go 11 | func (c *AuthorizerClient) DeactivateAccount(headers map[string]string) (*Response, error) { 12 | bytesData, err := c.ExecuteGraphQL(&GraphQLRequest{ 13 | Query: `mutation deactivateAccount { deactivate_account { message } }`, 14 | Variables: nil, 15 | }, headers) 16 | if err != nil { 17 | return nil, err 18 | } 19 | 20 | var res map[string]*Response 21 | json.Unmarshal(bytesData, &res) 22 | 23 | return res["deactivate_account"], nil 24 | } 25 | -------------------------------------------------------------------------------- /examples/client.go: -------------------------------------------------------------------------------- 1 | package examples 2 | 3 | const ( 4 | // Authorizer client identifier, obtained from authorizer dashboard 5 | ClientID = "19ccbbe2-7750-4aac-9d71-e2c75fbf660a" 6 | // Authorizer server endpoint 7 | AuthorizerURL = "http://localhost:8080" 8 | ) 9 | 10 | var ( 11 | // Test email 12 | TestEmail = "test@yopmail.com" 13 | ) 14 | -------------------------------------------------------------------------------- /examples/deactivate_account.go: -------------------------------------------------------------------------------- 1 | package examples 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/authorizerdev/authorizer-go" 7 | ) 8 | 9 | // DeactivateAccountExample demonstrates how to use DeactivateAccount function of authorizer sdk 10 | func DeactivateAccountExample() { 11 | c, err := authorizer.NewAuthorizerClient(ClientID, AuthorizerURL, "", nil) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | loginRes, err := c.Login(&authorizer.LoginInput{ 17 | Email: &TestEmail, 18 | Password: "Abc@123", 19 | }) 20 | if err != nil { 21 | panic(err) 22 | } 23 | 24 | res, err := c.DeactivateAccount(map[string]string{ 25 | "Authorization": fmt.Sprintf("Bearer %s", authorizer.StringValue(loginRes.AccessToken)), 26 | }) 27 | if err != nil { 28 | panic(err) 29 | } 30 | 31 | fmt.Println(res.Message) 32 | } 33 | -------------------------------------------------------------------------------- /examples/forgot_password.go: -------------------------------------------------------------------------------- 1 | package examples 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/authorizerdev/authorizer-go" 7 | ) 8 | 9 | // ForgotPasswordInputExample demonstrates how to use ForgotPassword function of authorizer skd 10 | func ForgotPasswordInputExample() { 11 | c, err := authorizer.NewAuthorizerClient(ClientID, AuthorizerURL, "", nil) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | res, err := c.ForgotPassword(&authorizer.ForgotPasswordInput{ 17 | Email: "test@yopmail.com", 18 | }) 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | fmt.Println(res.Message) 24 | } 25 | -------------------------------------------------------------------------------- /examples/get_meta_data.go: -------------------------------------------------------------------------------- 1 | package examples 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/authorizerdev/authorizer-go" 7 | ) 8 | 9 | // GetMetaDataExample demonstrates how to use GetMetaData function of authorizer sdk 10 | func GetMetaDataExample() { 11 | c, err := authorizer.NewAuthorizerClient(ClientID, AuthorizerURL, "", nil) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | res, err := c.GetMetaData() 17 | if err != nil { 18 | panic(err) 19 | } 20 | 21 | fmt.Println(res.Version, res.ClientID) 22 | } 23 | -------------------------------------------------------------------------------- /examples/get_profile.go: -------------------------------------------------------------------------------- 1 | package examples 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/authorizerdev/authorizer-go" 7 | ) 8 | 9 | // GetProfileExample demonstrates how to use GetProfile function of authorizer sdk 10 | func GetProfileExample() { 11 | c, err := authorizer.NewAuthorizerClient(ClientID, AuthorizerURL, "", nil) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | loginRes, err := c.Login(&authorizer.LoginInput{ 17 | Email: &TestEmail, 18 | Password: "Abc@123", 19 | }) 20 | if err != nil { 21 | panic(err) 22 | } 23 | 24 | res, err := c.GetProfile(map[string]string{ 25 | "Authorization": fmt.Sprintf("Bearer %s", authorizer.StringValue(loginRes.AccessToken)), 26 | }) 27 | if err != nil { 28 | panic(err) 29 | } 30 | 31 | fmt.Println(res.Email) 32 | } 33 | -------------------------------------------------------------------------------- /examples/get_session.go: -------------------------------------------------------------------------------- 1 | package examples 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/authorizerdev/authorizer-go" 7 | ) 8 | 9 | // GetSessionExample demonstrates how to use GetSession function of authorizer sdk 10 | func GetSessionExample() { 11 | c, err := authorizer.NewAuthorizerClient(ClientID, AuthorizerURL, "", nil) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | loginRes, err := c.Login(&authorizer.LoginInput{ 17 | Email: &TestEmail, 18 | Password: "Abc@123", 19 | }) 20 | if err != nil { 21 | panic(err) 22 | } 23 | 24 | res, err := c.GetSession(&authorizer.SessionQueryInput{ 25 | Roles: []*string{authorizer.NewStringRef("test")}, 26 | }, map[string]string{ 27 | "Authorization": fmt.Sprintf("Bearer %s", authorizer.StringValue(loginRes.AccessToken)), 28 | }) 29 | if err != nil { 30 | panic(err) 31 | } 32 | 33 | fmt.Println(authorizer.StringValue(res.Message)) 34 | } 35 | -------------------------------------------------------------------------------- /examples/login.go: -------------------------------------------------------------------------------- 1 | package examples 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/authorizerdev/authorizer-go" 7 | ) 8 | 9 | // LoginExample demonstrates how to use Login function of authorizer sdk 10 | func LoginExample() { 11 | c, err := authorizer.NewAuthorizerClient(ClientID, AuthorizerURL, "", nil) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | res, err := c.Login(&authorizer.LoginInput{ 17 | Email: &TestEmail, 18 | Password: "Abc@123", 19 | }) 20 | if err != nil { 21 | panic(err) 22 | } 23 | 24 | fmt.Println(authorizer.StringValue(res.Message)) 25 | } 26 | -------------------------------------------------------------------------------- /examples/logout.go: -------------------------------------------------------------------------------- 1 | package examples 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/authorizerdev/authorizer-go" 7 | ) 8 | 9 | // LogoutExample demonstrates how to use Logout function of authorizer sdk 10 | func LogoutExample() { 11 | c, err := authorizer.NewAuthorizerClient(ClientID, AuthorizerURL, "", nil) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | loginRes, err := c.Login(&authorizer.LoginInput{ 17 | Email: &TestEmail, 18 | Password: "Abc@123", 19 | }) 20 | if err != nil { 21 | panic(err) 22 | } 23 | 24 | res, err := c.Logout(map[string]string{ 25 | "Authorization": fmt.Sprintf("Bearer %s", authorizer.StringValue(loginRes.AccessToken)), 26 | }) 27 | if err != nil { 28 | panic(err) 29 | } 30 | 31 | fmt.Println(res.Message) 32 | } 33 | -------------------------------------------------------------------------------- /examples/magic_link_login.go: -------------------------------------------------------------------------------- 1 | package examples 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/authorizerdev/authorizer-go" 7 | ) 8 | 9 | // MagicLinkLoginExample demonstrates how to use MagicLinkLogin function of authorizer sdk 10 | func MagicLinkLoginExample() { 11 | c, err := authorizer.NewAuthorizerClient(ClientID, AuthorizerURL, "", nil) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | res, err := c.MagicLinkLogin(&authorizer.MagicLinkLoginInput{ 17 | Email: "test@yopmail.com", 18 | }) 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | fmt.Println(res.Message) 24 | } 25 | -------------------------------------------------------------------------------- /examples/resend_otp.go: -------------------------------------------------------------------------------- 1 | package examples 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/authorizerdev/authorizer-go" 7 | ) 8 | 9 | // ResendOTPExample demonstrates how to use ResendOTP function of authorizer sdk 10 | func ResendOTPExample() { 11 | c, err := authorizer.NewAuthorizerClient(ClientID, AuthorizerURL, "", nil) 12 | if err != nil { 13 | panic(err) 14 | } 15 | email := "test@yopmail.com" 16 | res, err := c.ResendOTP(&authorizer.ResendOTPInput{ 17 | Email: &email, 18 | }) 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | fmt.Println(res.Message) 24 | } 25 | -------------------------------------------------------------------------------- /examples/reset_password.go: -------------------------------------------------------------------------------- 1 | package examples 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/authorizerdev/authorizer-go" 7 | ) 8 | 9 | // ResetPasswordExample demonstrates how to use ResetPassword function of authorizer sdk 10 | func ResetPasswordExample() { 11 | c, err := authorizer.NewAuthorizerClient(ClientID, AuthorizerURL, "", nil) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | res, err := c.ResetPassword(&authorizer.ResetPasswordInput{ 17 | Token: "token obtained via forgot password email", 18 | Password: "new password", 19 | ConfirmPassword: "new password", 20 | }) 21 | if err != nil { 22 | panic(err) 23 | } 24 | 25 | fmt.Println(res.Message) 26 | } 27 | -------------------------------------------------------------------------------- /examples/revoke_token.go: -------------------------------------------------------------------------------- 1 | package examples 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/authorizerdev/authorizer-go" 7 | ) 8 | 9 | // RevokeTokenExample demonstrates how to use RevokeToken function of authorizer sdk 10 | func RevokeTokenExample() { 11 | c, err := authorizer.NewAuthorizerClient(ClientID, AuthorizerURL, "", nil) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | res, err := c.RevokeToken(&authorizer.RevokeTokenInput{ 17 | RefreshToken: "example refresh token", 18 | }) 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | fmt.Println(res.Message) 24 | } 25 | -------------------------------------------------------------------------------- /examples/signup.go: -------------------------------------------------------------------------------- 1 | package examples 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/authorizerdev/authorizer-go" 7 | ) 8 | 9 | // SignUpExample demonstrates how to use SignUp function of authorizer sdk 10 | func SignUpExample() { 11 | c, err := authorizer.NewAuthorizerClient(ClientID, AuthorizerURL, "", nil) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | res, err := c.SignUp(&authorizer.SignUpInput{ 17 | Email: &TestEmail, 18 | Password: "Abc@123", 19 | ConfirmPassword: "Abc@123", 20 | }) 21 | if err != nil { 22 | panic(err) 23 | } 24 | 25 | fmt.Println(authorizer.StringValue(res.Message)) 26 | } 27 | -------------------------------------------------------------------------------- /examples/update_profile.go: -------------------------------------------------------------------------------- 1 | package examples 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/authorizerdev/authorizer-go" 7 | ) 8 | 9 | // UpdateProfileExample demonstrates how to use UpdateProfile function of authorizer sdk 10 | func UpdateProfileExample() { 11 | c, err := authorizer.NewAuthorizerClient(ClientID, AuthorizerURL, "", nil) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | loginRes, err := c.Login(&authorizer.LoginInput{ 17 | Email: &TestEmail, 18 | Password: "Abc@123", 19 | }) 20 | if err != nil { 21 | panic(err) 22 | } 23 | 24 | res, err := c.UpdateProfile(&authorizer.UpdateProfileInput{ 25 | FamilyName: authorizer.NewStringRef("test"), 26 | }, map[string]string{ 27 | "Authorization": fmt.Sprintf("Bearer %s", authorizer.StringValue(loginRes.AccessToken)), 28 | }) 29 | if err != nil { 30 | panic(err) 31 | } 32 | 33 | fmt.Println(res.Message) 34 | } 35 | -------------------------------------------------------------------------------- /examples/validate_jwt_token.go: -------------------------------------------------------------------------------- 1 | package examples 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/authorizerdev/authorizer-go" 7 | ) 8 | 9 | // ValidateJWTTokenExample demonstrates how to use ValidateJWTToken function of authorizer sdk 10 | func ValidateJWTTokenExample() { 11 | c, err := authorizer.NewAuthorizerClient(ClientID, AuthorizerURL, "", nil) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | loginRes, err := c.Login(&authorizer.LoginInput{ 17 | Email: &TestEmail, 18 | Password: "Abc@123", 19 | }) 20 | if err != nil { 21 | panic(err) 22 | } 23 | 24 | res, err := c.ValidateJWTToken(&authorizer.ValidateJWTTokenInput{ 25 | TokenType: authorizer.TokenTypeAccessToken, 26 | Token: authorizer.StringValue(loginRes.AccessToken), 27 | }) 28 | if err != nil { 29 | panic(err) 30 | } 31 | 32 | fmt.Println(res.IsValid) 33 | } 34 | -------------------------------------------------------------------------------- /examples/validate_session.go: -------------------------------------------------------------------------------- 1 | package examples 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/authorizerdev/authorizer-go" 7 | ) 8 | 9 | // ValidateSessionExample demonstrates how to use ValidateSession function of authorizer sdk 10 | func ValidateSessionExample() { 11 | c, err := authorizer.NewAuthorizerClient(ClientID, AuthorizerURL, "", nil) 12 | if err != nil { 13 | panic(err) 14 | } 15 | _, err = c.Login(&authorizer.LoginInput{ 16 | Email: &TestEmail, 17 | Password: "Abc@123", 18 | }) 19 | if err != nil { 20 | panic(err) 21 | } 22 | res, err := c.ValidateSession(&authorizer.ValidateSessionInput{ 23 | Cookie: "", // TODO set cookie here 24 | }) 25 | if err != nil { 26 | panic(err) 27 | } 28 | fmt.Println(res.IsValid) 29 | } 30 | -------------------------------------------------------------------------------- /examples/verify_email.go: -------------------------------------------------------------------------------- 1 | package examples 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/authorizerdev/authorizer-go" 7 | ) 8 | 9 | // VerifyEmailExample demonstrates how to use VerifyEmail function of authorizer sdk 10 | func VerifyEmailExample() { 11 | c, err := authorizer.NewAuthorizerClient(ClientID, AuthorizerURL, "", nil) 12 | if err != nil { 13 | panic(err) 14 | } 15 | 16 | res, err := c.VerifyEmail(&authorizer.VerifyEmailInput{ 17 | Token: "token sent via email", 18 | }) 19 | if err != nil { 20 | panic(err) 21 | } 22 | 23 | fmt.Println(authorizer.StringValue(res.AccessToken)) 24 | } 25 | -------------------------------------------------------------------------------- /examples/verify_otp.go: -------------------------------------------------------------------------------- 1 | package examples 2 | 3 | import ( 4 | "fmt" 5 | 6 | "github.com/authorizerdev/authorizer-go" 7 | ) 8 | 9 | // VerifyOTPExample demonstrates how to use VerifyOTP function of authorizer sdk 10 | func VerifyOTPExample() { 11 | c, err := authorizer.NewAuthorizerClient(ClientID, AuthorizerURL, "", nil) 12 | if err != nil { 13 | panic(err) 14 | } 15 | email := "test@yopmail.com" 16 | res, err := c.VerifyOTP(&authorizer.VerifyOTPInput{ 17 | OTP: "test", 18 | Email: &email, 19 | }) 20 | if err != nil { 21 | panic(err) 22 | } 23 | 24 | fmt.Println(authorizer.StringValue(res.AccessToken)) 25 | } 26 | -------------------------------------------------------------------------------- /forgot_password.go: -------------------------------------------------------------------------------- 1 | package authorizer 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | // ForgotPasswordInput defines attributes for forgot_password request 8 | type ForgotPasswordInput struct { 9 | Email string `json:"email"` 10 | State *string `json:"state,omitempty"` 11 | RedirectURI *string `json:"redirect_uri,omitempty"` 12 | } 13 | 14 | // ForgotPassword is method attached to AuthorizerClient. 15 | // It performs forgot_password mutation on authorizer instance. 16 | // It takes ForgotPasswordInput reference as parameter and returns Response reference or error. 17 | // For implementation details check ForgotPasswordInputExample in examples/forgot_password.go 18 | func (c *AuthorizerClient) ForgotPassword(req *ForgotPasswordInput) (*Response, error) { 19 | if req.State == nil || StringValue(req.State) == "" { 20 | // generate random state 21 | req.State = NewStringRef(EncodeB64(CreateRandomString())) 22 | } 23 | 24 | if req.RedirectURI == nil || StringValue(req.RedirectURI) == "" { 25 | req.RedirectURI = NewStringRef(c.RedirectURL) 26 | } 27 | 28 | bytesData, err := c.ExecuteGraphQL(&GraphQLRequest{ 29 | Query: `mutation forgotPassword($data: ForgotPasswordInput!) { forgot_password(params: $data) { message } }`, 30 | Variables: map[string]interface{}{ 31 | "data": req, 32 | }, 33 | }, nil) 34 | if err != nil { 35 | return nil, err 36 | } 37 | 38 | var res map[string]*Response 39 | json.Unmarshal(bytesData, &res) 40 | 41 | return res["forgot_password"], nil 42 | } 43 | -------------------------------------------------------------------------------- /get_meta_data.go: -------------------------------------------------------------------------------- 1 | package authorizer 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | // MetaDataResponse defines attributes for MetaData response query 8 | type MetaDataResponse struct { 9 | Version string `json:"version"` 10 | ClientID string `json:"client_id"` 11 | IsGoogleLoginEnabled bool `json:"is_google_login_enabled"` 12 | IsFacebookLoginEnabled bool `json:"is_facebook_login_enabled"` 13 | IsGithubLoginEnabled bool `json:"is_github_login_enabled"` 14 | IsLinkedinLoginEnabled bool `json:"is_linkedin_login_enabled"` 15 | IsAppleLoginEnabled bool `json:"is_apple_login_enabled"` 16 | IsTwitterLoginEnabled bool `json:"is_twitter_login_enabled"` 17 | IsEmailVerificationEnabled bool `json:"is_email_verification_enabled"` 18 | IsBasicAuthenticationEnabled bool `json:"is_basic_authentication_enabled"` 19 | IsMagicLinkLoginEnabled bool `json:"is_magic_link_login_enabled"` 20 | IsSignUpEnabled bool `json:"is_sign_up_enabled"` 21 | IsStrongPasswordEnabled bool `json:"is_strong_password_enabled"` 22 | } 23 | 24 | // GetMetaData is method attached to AuthorizerClient. 25 | // It performs meta query on authorizer instance. 26 | // It returns MetaResponse reference or error. 27 | // For implementation details check GetMetadataExample examples/get_meta_data.go 28 | func (c *AuthorizerClient) GetMetaData() (*MetaDataResponse, error) { 29 | bytesData, err := c.ExecuteGraphQL(&GraphQLRequest{ 30 | Query: `query { meta { version client_id is_google_login_enabled is_facebook_login_enabled is_github_login_enabled is_linkedin_login_enabled is_apple_login_enabled is_twitter_login_enabled is_email_verification_enabled is_basic_authentication_enabled is_magic_link_login_enabled is_sign_up_enabled is_strong_password_enabled } }`, 31 | Variables: nil, 32 | }, nil) 33 | if err != nil { 34 | return nil, err 35 | } 36 | 37 | var res map[string]*MetaDataResponse 38 | json.Unmarshal(bytesData, &res) 39 | 40 | return res["meta"], nil 41 | } 42 | -------------------------------------------------------------------------------- /get_profile.go: -------------------------------------------------------------------------------- 1 | package authorizer 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | // GetProfile is method attached to AuthorizerClient. 9 | // It performs profile query on authorizer instance. 10 | // It returns User reference or error. 11 | // For implementation details check GetProfileExample examples/get_profile.go 12 | func (c *AuthorizerClient) GetProfile(headers map[string]string) (*User, error) { 13 | bytesData, err := c.ExecuteGraphQL(&GraphQLRequest{ 14 | Query: fmt.Sprintf(`query { profile { %s } }`, UserFragment), 15 | Variables: nil, 16 | }, headers) 17 | if err != nil { 18 | return nil, err 19 | } 20 | 21 | var res map[string]*User 22 | json.Unmarshal(bytesData, &res) 23 | 24 | return res["profile"], nil 25 | } 26 | -------------------------------------------------------------------------------- /get_session.go: -------------------------------------------------------------------------------- 1 | package authorizer 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | // SessionQueryInput defines attributes for session query request 9 | type SessionQueryInput struct { 10 | Roles []*string `json:"roles"` 11 | } 12 | 13 | // TODO: session currently works with cookie only use this function once the flow is fixed in authorizer core. 14 | 15 | // GetSession is method attached to AuthorizerClient. 16 | // It performs session query on authorizer instance. 17 | // It returns User reference or error. 18 | // For implementation details check GetSessionExample examples/get_session.go 19 | func (c *AuthorizerClient) GetSession(req *SessionQueryInput, headers map[string]string) (*AuthTokenResponse, error) { 20 | bytesData, err := c.ExecuteGraphQL(&GraphQLRequest{ 21 | Query: fmt.Sprintf(`query getSession($data: SessionQueryInput){session(params: $data) { %s } }`, AuthTokenResponseFragment), 22 | Variables: map[string]interface{}{ 23 | "data": req, 24 | }, 25 | }, headers) 26 | if err != nil { 27 | return nil, err 28 | } 29 | 30 | var res map[string]*AuthTokenResponse 31 | json.Unmarshal(bytesData, &res) 32 | 33 | return res["session"], nil 34 | } 35 | -------------------------------------------------------------------------------- /get_token.go: -------------------------------------------------------------------------------- 1 | package authorizer 2 | 3 | import "errors" 4 | 5 | // TokenQueryInput defines attributes for token request 6 | type TokenQueryInput struct { 7 | Code *string `json:"code"` 8 | GrantType *string `json:"grant_type"` 9 | RefreshToken *string `json:"refresh_token"` 10 | } 11 | 12 | // TODO check if we can use oauth get token from backend 13 | 14 | // TokenResponse defines attributes for token request 15 | type TokenResponse struct { 16 | AccessToken string `json:"access_token"` 17 | ExpiresIn int64 `json:"expires_in"` 18 | IdToken string `json:"id_token"` 19 | RefreshToken *string `json:"refresh_token"` 20 | } 21 | 22 | // GetToken is method attached to AuthorizerClient. 23 | // It performs `/oauth/token` query on authorizer instance. 24 | // It returns User reference or error. 25 | // For implementation details check GetTokenExample examples/get_token.go 26 | func (c *AuthorizerClient) GetToken(req *TokenQueryInput) (*TokenResponse, error) { 27 | grantType := StringValue(req.GrantType) 28 | if grantType == "" { 29 | req.GrantType = NewStringRef(GrantTypeAuthorizationCode) 30 | } 31 | 32 | if grantType == GrantTypeRefreshToken && req.RefreshToken == nil { 33 | return nil, errors.New("invalid refresh token") 34 | } 35 | 36 | return nil, nil 37 | } 38 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/authorizerdev/authorizer-go 2 | 3 | go 1.17 4 | -------------------------------------------------------------------------------- /graphql.go: -------------------------------------------------------------------------------- 1 | package authorizer 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "errors" 7 | "io/ioutil" 8 | "net/http" 9 | ) 10 | 11 | // GraphQLRequest is object used to make graphql queries 12 | type GraphQLRequest struct { 13 | Query string `json:"query"` 14 | Variables map[string]interface{} `json:"variables,omitempty"` 15 | } 16 | 17 | type GraphQLError struct { 18 | Message string `json:"message"` 19 | Path []string `json:"path"` 20 | } 21 | type GraphQLResponse struct { 22 | Errors []*GraphQLError `json:"errors"` 23 | Data interface{} `json:"data"` 24 | } 25 | 26 | func (c *AuthorizerClient) ExecuteGraphQL(req *GraphQLRequest, headers map[string]string) ([]byte, error) { 27 | // Marshal it into JSON prior to requesting 28 | jsonReq, err := json.Marshal(req) 29 | if err != nil { 30 | return nil, err 31 | } 32 | 33 | client := http.Client{} 34 | httpReq, err := http.NewRequest(http.MethodPost, c.AuthorizerURL+"/graphql", bytes.NewReader(jsonReq)) 35 | if err != nil { 36 | return nil, err 37 | } 38 | 39 | // set the content type for http request 40 | httpReq.Header.Set("Content-Type", "application/json") 41 | 42 | // set the default extra headers 43 | for key, val := range c.ExtraHeaders { 44 | httpReq.Header.Add(key, val) 45 | } 46 | 47 | // set the headers for this request 48 | if headers != nil { 49 | for key, val := range headers { 50 | httpReq.Header.Add(key, val) 51 | } 52 | } 53 | 54 | res, err := client.Do(httpReq) 55 | if err != nil { 56 | return nil, err 57 | } 58 | // Need to close the response stream, once response is read. 59 | // Hence defer close. It will automatically take care of it. 60 | defer res.Body.Close() 61 | 62 | bodyBytes, err := ioutil.ReadAll(res.Body) 63 | if err != nil { 64 | return nil, err 65 | } 66 | 67 | var gqlRes *GraphQLResponse 68 | err = json.Unmarshal(bodyBytes, &gqlRes) 69 | if err != nil { 70 | return nil, err 71 | } 72 | 73 | if len(gqlRes.Errors) > 0 { 74 | return nil, errors.New(gqlRes.Errors[0].Message) 75 | } 76 | 77 | dataBytes, err := json.Marshal(gqlRes.Data) 78 | if err != nil { 79 | return nil, err 80 | } 81 | 82 | return dataBytes, nil 83 | } 84 | -------------------------------------------------------------------------------- /login.go: -------------------------------------------------------------------------------- 1 | package authorizer 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | // LoginInput defines attributes for login request 9 | type LoginInput struct { 10 | Email *string `json:"email,omitempty"` 11 | PhoneNumber *string `json:"phone_number,omitempty"` 12 | Password string `json:"password"` 13 | Roles []*string `json:"roles,omitempty"` 14 | Scope []*string `json:"scope,omitempty"` 15 | } 16 | 17 | // Login is method attached to AuthorizerClient. 18 | // It performs login mutation on authorizer instance. 19 | // It takes LoginInput reference as parameter and returns AuthTokenResponse reference or error. 20 | // For implementation details check LoginExample examples/login.go 21 | func (c *AuthorizerClient) Login(req *LoginInput) (*AuthTokenResponse, error) { 22 | bytesData, err := c.ExecuteGraphQL(&GraphQLRequest{ 23 | Query: fmt.Sprintf(`mutation login($data: LoginInput!) { login(params: $data) { %s } }`, AuthTokenResponseFragment), 24 | Variables: map[string]interface{}{ 25 | "data": req, 26 | }, 27 | }, nil) 28 | if err != nil { 29 | return nil, err 30 | } 31 | 32 | var res map[string]*AuthTokenResponse 33 | json.Unmarshal(bytesData, &res) 34 | 35 | return res["login"], nil 36 | } 37 | -------------------------------------------------------------------------------- /logout.go: -------------------------------------------------------------------------------- 1 | package authorizer 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | // TODO does not work without cookie 8 | 9 | // Logout is method attached to AuthorizerClient. 10 | // It performs Logout mutation on authorizer instance. 11 | // It takes LogoutInput reference as parameter and returns Response reference or error. 12 | // For implementation details check LogoutExample examples/Logout.go 13 | func (c *AuthorizerClient) Logout(headers map[string]string) (*Response, error) { 14 | bytesData, err := c.ExecuteGraphQL(&GraphQLRequest{ 15 | Query: `mutation { logout { message } }`, 16 | Variables: nil, 17 | }, headers) 18 | if err != nil { 19 | return nil, err 20 | } 21 | 22 | var res map[string]*Response 23 | json.Unmarshal(bytesData, &res) 24 | 25 | return res["logout"], nil 26 | } 27 | -------------------------------------------------------------------------------- /magic_link_login.go: -------------------------------------------------------------------------------- 1 | package authorizer 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | // MagicLinkLoginInput defines attributes for magic link login request 8 | type MagicLinkLoginInput struct { 9 | Email string `json:"email"` 10 | Roles []*string `json:"roles,omitempty"` 11 | Scope []*string `json:"scope,omitempty"` 12 | State *string `json:"state"` 13 | RedirectURI *string `json:"redirect_uri"` 14 | } 15 | 16 | // MagicLinkLoginInput is method attached to AuthorizerClient. 17 | // It performs magic_link_login mutation on authorizer instance. 18 | // It takes MagicLinkLoginInput reference as parameter and returns AuthTokenResponse reference or error. 19 | // For implementation details check MagicLinkLoginExample examples/magic_link_login.go 20 | func (c *AuthorizerClient) MagicLinkLogin(req *MagicLinkLoginInput) (*Response, error) { 21 | if req.State == nil || StringValue(req.State) == "" { 22 | // generate random state 23 | req.State = NewStringRef(EncodeB64(CreateRandomString())) 24 | } 25 | 26 | if req.RedirectURI == nil || StringValue(req.RedirectURI) == "" { 27 | req.RedirectURI = NewStringRef(c.RedirectURL) 28 | } 29 | 30 | bytesData, err := c.ExecuteGraphQL(&GraphQLRequest{ 31 | Query: `mutation magicLinkLogin($data: MagicLinkLoginInput!) { magic_link_login(params: $data) { message }}`, 32 | Variables: map[string]interface{}{ 33 | "data": req, 34 | }, 35 | }, nil) 36 | if err != nil { 37 | return nil, err 38 | } 39 | 40 | var res map[string]*Response 41 | json.Unmarshal(bytesData, &res) 42 | 43 | return res["magic_link_login"], nil 44 | } 45 | -------------------------------------------------------------------------------- /resend_otp.go: -------------------------------------------------------------------------------- 1 | package authorizer 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | // ResendOTPInput defines attributes for resend_otp request 8 | type ResendOTPInput struct { 9 | Email *string `json:"email"` 10 | PhoneNumber *string `json:"phone_number"` 11 | } 12 | 13 | // ResendOTP is method attached to AuthorizerClient. 14 | // It performs resend_otp mutation on authorizer instance. 15 | // It takes ResendOTPInput reference as parameter and returns Response reference or error. 16 | // For implementation details check ResendOTPExample examples/resend_otp.go 17 | func (c *AuthorizerClient) ResendOTP(req *ResendOTPInput) (*Response, error) { 18 | bytesData, err := c.ExecuteGraphQL(&GraphQLRequest{ 19 | Query: `mutation resendOtp($data: ResendOTPRequest!) { resend_otp(params: $data) { message }}`, 20 | Variables: map[string]interface{}{ 21 | "data": req, 22 | }, 23 | }, nil) 24 | if err != nil { 25 | return nil, err 26 | } 27 | 28 | var res map[string]*Response 29 | json.Unmarshal(bytesData, &res) 30 | 31 | return res["resend_otp"], nil 32 | } 33 | -------------------------------------------------------------------------------- /reset_password.go: -------------------------------------------------------------------------------- 1 | package authorizer 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | // ResetPasswordInput defines attributes for reset_password request 8 | type ResetPasswordInput struct { 9 | Token string `json:"token"` 10 | Password string `json:"password"` 11 | ConfirmPassword string `json:"confirm_password"` 12 | } 13 | 14 | // ResetPassword is method attached to AuthorizerClient. 15 | // It performs resend_otp mutation on authorizer instance. 16 | // It takes ResetPasswordInput reference as parameter and returns Response reference or error. 17 | // For implementation details check ResetPasswordExample examples/resent_password.go 18 | func (c *AuthorizerClient) ResetPassword(req *ResetPasswordInput) (*Response, error) { 19 | bytesData, err := c.ExecuteGraphQL(&GraphQLRequest{ 20 | Query: `mutation resetPassword($data: ResetPasswordInput!) { reset_password(params: $data) { message } }`, 21 | Variables: map[string]interface{}{ 22 | "data": req, 23 | }, 24 | }, nil) 25 | if err != nil { 26 | return nil, err 27 | } 28 | 29 | var res map[string]*Response 30 | json.Unmarshal(bytesData, &res) 31 | 32 | return res["reset_password"], nil 33 | } 34 | -------------------------------------------------------------------------------- /revoke_token.go: -------------------------------------------------------------------------------- 1 | package authorizer 2 | 3 | import ( 4 | "bytes" 5 | "encoding/json" 6 | "errors" 7 | "io/ioutil" 8 | "net/http" 9 | ) 10 | 11 | // RevokeTokenInput defines attributes for /oauth/revoke request 12 | type RevokeTokenInput struct { 13 | RefreshToken string `json:"refresh_token"` 14 | } 15 | 16 | // RevokeToken is method attached to AuthorizerClient. 17 | // It performs /oauth/revoke api call on authorizer instance. 18 | // It takes RevokeTokenInput reference as parameter and returns Response reference or error. 19 | // For implementation details check RevokeTokenExample examples/revoke_token.go 20 | func (c *AuthorizerClient) RevokeToken(req *RevokeTokenInput) (*Response, error) { 21 | if req.RefreshToken == "" { 22 | return nil, errors.New("refresh_token is required") 23 | } 24 | // Marshal it into JSON prior to requesting 25 | jsonReq, err := json.Marshal(map[string]string{ 26 | "refresh_token": req.RefreshToken, 27 | "client_id": c.ClientID, 28 | }) 29 | if err != nil { 30 | return nil, err 31 | } 32 | 33 | client := http.Client{} 34 | httpReq, err := http.NewRequest(http.MethodPost, c.AuthorizerURL+"/oauth/revoke", bytes.NewReader(jsonReq)) 35 | if err != nil { 36 | return nil, err 37 | } 38 | 39 | // set the default extra headers 40 | for key, val := range c.ExtraHeaders { 41 | httpReq.Header.Add(key, val) 42 | } 43 | 44 | httpRes, err := client.Do(httpReq) 45 | if err != nil { 46 | return nil, err 47 | } 48 | // Need to close the response stream, once response is read. 49 | // Hence defer close. It will automatically take care of it. 50 | defer httpRes.Body.Close() 51 | 52 | bodyBytes, err := ioutil.ReadAll(httpRes.Body) 53 | if err != nil { 54 | return nil, err 55 | } 56 | 57 | var res *Response 58 | json.Unmarshal(bodyBytes, &res) 59 | 60 | return res, nil 61 | } 62 | -------------------------------------------------------------------------------- /signup.go: -------------------------------------------------------------------------------- 1 | package authorizer 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | // SignUpInput defines attributes for signup request 9 | type SignUpInput struct { 10 | Email *string `json:"email,omitempty"` 11 | Password string `json:"password"` 12 | ConfirmPassword string `json:"confirm_password"` 13 | GivenName *string `json:"given_name,omitempty"` 14 | FamilyName *string `json:"family_name,omitempty"` 15 | MiddleName *string `json:"middle_name,omitempty"` 16 | NickName *string `json:"nick_name,omitempty"` 17 | Picture *string `json:"picture,omitempty"` 18 | Gender *string `json:"gender,omitempty"` 19 | BirthDate *string `json:"birthdate,omitempty"` 20 | PhoneNumber *string `json:"phone_number,omitempty"` 21 | Roles []*string `json:"roles,omitempty"` 22 | Scope []*string `json:"scope,omitempty"` 23 | RedirectURI *string `json:"redirect_uri,omitempty"` 24 | IsMultiFactorAuthEnabled *bool `json:"is_multi_factor_auth_enabled,omitempty"` 25 | AppData map[string]interface{} `json:"app_data,omitempty"` 26 | } 27 | 28 | // SignUp is method attached to AuthorizerClient. 29 | // It performs signup mutation on authorizer instance. 30 | // It takes SignUpInput reference as parameter and returns AuthTokenResponse reference or error. 31 | // For implementation details check SignUpExample examples/signup.go 32 | func (c *AuthorizerClient) SignUp(req *SignUpInput) (*AuthTokenResponse, error) { 33 | bytesData, err := c.ExecuteGraphQL(&GraphQLRequest{ 34 | Query: fmt.Sprintf(`mutation signup($data: SignUpInput!) { signup(params: $data) { %s }}`, AuthTokenResponseFragment), 35 | Variables: map[string]interface{}{ 36 | "data": req, 37 | }, 38 | }, nil) 39 | if err != nil { 40 | return nil, err 41 | } 42 | 43 | var res map[string]*AuthTokenResponse 44 | json.Unmarshal(bytesData, &res) 45 | 46 | return res["signup"], nil 47 | } 48 | -------------------------------------------------------------------------------- /test/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import "github.com/authorizerdev/authorizer-go/examples" 4 | 5 | func main() { 6 | // examples.LoginExample() 7 | // examples.ForgotPasswordInputExample() 8 | // examples.GetMetaDataExample() 9 | // examples.GetProfileExample() 10 | // examples.GetSessionExample() 11 | // examples.LogoutExample() 12 | // examples.MagicLinkLoginExample() 13 | // examples.ValidateJWTTokenExample() 14 | examples.SignUpExample() 15 | } 16 | -------------------------------------------------------------------------------- /update_profile.go: -------------------------------------------------------------------------------- 1 | package authorizer 2 | 3 | import ( 4 | "encoding/json" 5 | ) 6 | 7 | // UpdateProfileInput defines attributes for signup request 8 | type UpdateProfileInput struct { 9 | Email *string `json:"email,omitempty"` 10 | NewPassword *string `json:"new_password,omitempty"` 11 | ConfirmNewPassword *string `json:"confirm_new_password,omitempty"` 12 | OldPassword *string `json:"old_password,omitempty"` 13 | GivenName *string `json:"given_name,omitempty"` 14 | FamilyName *string `json:"family_name,omitempty"` 15 | MiddleName *string `json:"middle_name,omitempty"` 16 | NickName *string `json:"nick_name,omitempty"` 17 | Picture *string `json:"picture,omitempty"` 18 | Gender *string `json:"gender,omitempty"` 19 | BirthDate *string `json:"birthdate,omitempty"` 20 | PhoneNumber *string `json:"phone_number,omitempty"` 21 | Roles []*string `json:"roles,omitempty"` 22 | Scope []*string `json:"scope,omitempty"` 23 | RedirectURI *string `json:"redirect_uri,omitempty"` 24 | IsMultiFactorAuthEnabled *bool `json:"is_multi_factor_auth_enabled,omitempty"` 25 | AppData map[string]interface{} `json:"app_data,omitempty"` 26 | } 27 | 28 | // UpdateProfile is method attached to AuthorizerClient. 29 | // It performs update_profile mutation on authorizer instance. 30 | // It returns User reference or error. 31 | // For implementation details check UpdateProfileExample examples/update_profile.go 32 | func (c *AuthorizerClient) UpdateProfile(req *UpdateProfileInput, headers map[string]string) (*Response, error) { 33 | bytesData, err := c.ExecuteGraphQL(&GraphQLRequest{ 34 | Query: `mutation updateProfile($data: UpdateProfileInput!) { update_profile(params: $data) { message } }`, 35 | Variables: map[string]interface{}{ 36 | "data": req, 37 | }, 38 | }, headers) 39 | if err != nil { 40 | return nil, err 41 | } 42 | 43 | var res map[string]*Response 44 | json.Unmarshal(bytesData, &res) 45 | 46 | return res["update_profile"], nil 47 | } 48 | -------------------------------------------------------------------------------- /utils.go: -------------------------------------------------------------------------------- 1 | package authorizer 2 | 3 | import ( 4 | "encoding/base64" 5 | "math/rand" 6 | ) 7 | 8 | // CreateRandomString returns a random string 43 characters 9 | func CreateRandomString() string { 10 | letterBytes := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ" 11 | b := make([]byte, 43) 12 | for i := range b { 13 | b[i] = letterBytes[rand.Intn(len(letterBytes))] 14 | } 15 | return string(b) 16 | } 17 | 18 | // EncodeB64 returns string which is base64 encoded 19 | func EncodeB64(message string) string { 20 | base64Text := make([]byte, base64.StdEncoding.EncodedLen(len(message))) 21 | base64.StdEncoding.Encode(base64Text, []byte(message)) 22 | return string(base64Text) 23 | } 24 | 25 | // NewStringRef returns a reference to a string with given value 26 | func NewStringRef(v string) *string { 27 | return &v 28 | } 29 | 30 | // StringValue returns the value of the given string ref 31 | func StringValue(r *string, defaultValue ...string) string { 32 | if r != nil { 33 | return *r 34 | } 35 | if len(defaultValue) > 0 { 36 | return defaultValue[0] 37 | } 38 | return "" 39 | } 40 | -------------------------------------------------------------------------------- /validate_jwt_token.go: -------------------------------------------------------------------------------- 1 | package authorizer 2 | 3 | import "encoding/json" 4 | 5 | type TokenType string 6 | 7 | const ( 8 | // Token type access_token 9 | TokenTypeAccessToken TokenType = "access_token" 10 | // Token type id_token 11 | TokenTypeIDToken TokenType = "id_token" 12 | // Token type refresh_token 13 | TokenTypeRefreshToken TokenType = "refresh_token" 14 | ) 15 | 16 | // ValidateJWTTokenInput defines attributes for validate_jwt_token request 17 | type ValidateJWTTokenInput struct { 18 | TokenType TokenType `json:"token_type"` 19 | Token string `json:"token"` 20 | Roles []*string `json:"roles,omitempty"` 21 | } 22 | 23 | // ValidateJWTTokenResponse defines attributes for validate_jwt_token response 24 | 25 | type ValidateJWTTokenResponse struct { 26 | IsValid bool `json:"is_valid"` 27 | Claims map[string]interface{} `json:"claims"` 28 | } 29 | 30 | // ValidateJWTToken is method attached to AuthorizerClient. 31 | // It performs validate_jwt_token query on authorizer instance. 32 | // It returns ValidateJWTTokenResponse reference or error. 33 | // For implementation details check ValidateJWTTokenExample examples/validate_jwt_token.go 34 | func (c *AuthorizerClient) ValidateJWTToken(req *ValidateJWTTokenInput) (*ValidateJWTTokenResponse, error) { 35 | bytesData, err := c.ExecuteGraphQL(&GraphQLRequest{ 36 | Query: `query validateJWTToken($data: ValidateJWTTokenInput!){validate_jwt_token(params: $data) { is_valid claims } }`, 37 | Variables: map[string]interface{}{ 38 | "data": req, 39 | }, 40 | }, nil) 41 | if err != nil { 42 | return nil, err 43 | } 44 | 45 | var res map[string]*ValidateJWTTokenResponse 46 | json.Unmarshal(bytesData, &res) 47 | 48 | return res["validate_jwt_token"], nil 49 | } 50 | -------------------------------------------------------------------------------- /validate_session.go: -------------------------------------------------------------------------------- 1 | package authorizer 2 | 3 | import "encoding/json" 4 | 5 | // ValidateSessionInput defines attributes for validate_session request 6 | type ValidateSessionInput struct { 7 | Cookie string `json:"cookie,omitempty"` 8 | Roles []*string `json:"roles,omitempty"` 9 | } 10 | 11 | // ValidateSessionResponse defines attributes for validate_session response 12 | 13 | type ValidateSessionResponse struct { 14 | IsValid bool `json:"is_valid"` 15 | User *User `json:"user,omitempty"` 16 | } 17 | 18 | // ValidateSession is method attached to AuthorizerClient. 19 | // It performs validate_session query on authorizer instance. 20 | // It returns ValidateSessionResponse reference or error. 21 | // For implementation details check ValidateSessionExample examples/validate_session.go 22 | func (c *AuthorizerClient) ValidateSession(req *ValidateSessionInput) (*ValidateSessionResponse, error) { 23 | bytesData, err := c.ExecuteGraphQL(&GraphQLRequest{ 24 | Query: `query validateSession($data: ValidateSessionInput!){validate_session(params: $data) { is_valid user } }`, 25 | Variables: map[string]interface{}{ 26 | "data": req, 27 | }, 28 | }, nil) 29 | if err != nil { 30 | return nil, err 31 | } 32 | 33 | var res map[string]*ValidateSessionResponse 34 | json.Unmarshal(bytesData, &res) 35 | 36 | return res["validate_session"], nil 37 | } 38 | -------------------------------------------------------------------------------- /verify_email.go: -------------------------------------------------------------------------------- 1 | package authorizer 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | // VerifyEmailInput defines attributes for verify_email request 9 | type VerifyEmailInput struct { 10 | Token string `json:"token"` 11 | } 12 | 13 | // VerifyEmail is method attached to AuthorizerClient. 14 | // It performs verify_email mutation on authorizer instance. 15 | // It returns AuthTokenResponse reference or error. 16 | // For implementation details check VerifyEmailExample examples/verify_email.go 17 | func (c *AuthorizerClient) VerifyEmail(req *VerifyEmailInput) (*AuthTokenResponse, error) { 18 | bytesData, err := c.ExecuteGraphQL(&GraphQLRequest{ 19 | Query: fmt.Sprintf(`mutation verifyEmail($data: VerifyEmailInput!) { verify_email(params: $data) { %s}}`, AuthTokenResponseFragment), 20 | Variables: map[string]interface{}{ 21 | "data": req, 22 | }, 23 | }, nil) 24 | if err != nil { 25 | return nil, err 26 | } 27 | 28 | var res map[string]*AuthTokenResponse 29 | json.Unmarshal(bytesData, &res) 30 | 31 | return res["verify_email"], nil 32 | } 33 | -------------------------------------------------------------------------------- /verify_otp.go: -------------------------------------------------------------------------------- 1 | package authorizer 2 | 3 | import ( 4 | "encoding/json" 5 | "fmt" 6 | ) 7 | 8 | // VerifyOTPInput defines attributes for verify_otp request 9 | type VerifyOTPInput struct { 10 | Email *string `json:"email"` 11 | OTP string `json:"otp"` 12 | PhoneNumber *string `json:"phone_number"` 13 | } 14 | 15 | // VerifyOTP is method attached to AuthorizerClient. 16 | // It performs verify_otp mutation on authorizer instance. 17 | // It returns AuthTokenResponse reference or error. 18 | // For implementation details check VerifyOTPExample examples/verify_otp.go 19 | func (c *AuthorizerClient) VerifyOTP(req *VerifyOTPInput) (*AuthTokenResponse, error) { 20 | bytesData, err := c.ExecuteGraphQL(&GraphQLRequest{ 21 | Query: fmt.Sprintf(`mutation verifyOtp($data: VerifyOTPRequest!) { verify_otp(params: $data) { %s }}`, AuthTokenResponseFragment), 22 | Variables: map[string]interface{}{ 23 | "data": req, 24 | }, 25 | }, nil) 26 | if err != nil { 27 | return nil, err 28 | } 29 | 30 | var res map[string]*AuthTokenResponse 31 | json.Unmarshal(bytesData, &res) 32 | 33 | return res["verify_otp"], nil 34 | } 35 | --------------------------------------------------------------------------------